大家好,
请问从__global__里调用一个__device__的函数,根据手册:
When compiling code for devices of compute capability 1.x, a device function is always inlined by default. When compiling code for devices of compute capability 2.x and higher, a device function is only inlined when deemed appropriate by the compiler.
第一种情况很好理解,直接inline了,那么第二种情况呢?
那就应该如同常见的C函数嵌套调用,有一个参数传递之类的过程的吧?在"compute capablity 2.x and higher"上,这个参数传递是通过神马进行的?寄存器?device memory上的堆栈? 如果是寄存器,会增加寄存器的消耗吧,具体又是如何占用的?思考了一个多月了。。。百思不得其解。。谢谢!
求真相帝现身。
现说一个猜想,考虑到fermi上可以多个kernel并行(当然是通过stream实现的),那么调用device是否也是类似的机制呢?原kernel不退出,另外启动一个device函数。具体机制就不清楚了,这样的话,可以防止因为inline造成kernel内部寄存器不够用。不过具体的编译器的取舍也是不清楚的。
device__函数在最终编译后,实际上在cubin里总是被合并在__global__的代码流的尾部的,但不是直接inline的,而是在需要调用的时候对他CAL一次,被调用的__device(已合并到__global__的尾部)在执行完毕后是RET指令返回的。所以ICE的“原来不退出,另外启动啥的”说法是不对的。大家是在同一个代码流里的。没有额外启动什么东西。
关于楼主问的参数传递和现场保存,我记得是混合的,即:
(1)返回地址的保存总是通过堆栈的,不过fermi没有单独的堆栈寄存器,也没有单独的堆栈段,一般认为是相对local memory的特定位置上的。
(2)参数是通过寄存器传递的,而因为需要被参数使用的原寄存器的值,则被保存到另外的寄存器。
这些是实践中的结论,因为NV不发布他们的实际ABI规范。所以我们不能得知上文是否完全真实,请有选择的看。
感谢LS…基本明白了。
看来inline不inline唯一的好处就是节约代码长度了,对寄存器的消耗看来基本没好处,也基本没坏处。
可能对代码缓存有点好处。。