CUDA堆栈帧大小增加uuu forceinline__
当我使用CUDA堆栈帧大小增加uuu forceinline__,cuda,nvcc,Cuda,Nvcc,当我使用\uuu forceinline\uu声明设备功能时,链接器输出以下信息: 2> nvlink : info : Function properties for '_ZN3GPU4Flux4calcILj512EEEvv': 2> nvlink : info : used 28 registers, 456 stack, 15776 bytes smem, 320 bytes cmem[0], 0 bytes lmem 如果没有它,输出是: 2> nvlink
\uuu forceinline\uu
声明设备功能时,链接器输出以下信息:
2> nvlink : info : Function properties for '_ZN3GPU4Flux4calcILj512EEEvv':
2> nvlink : info : used 28 registers, 456 stack, 15776 bytes smem, 320 bytes cmem[0], 0 bytes lmem
如果没有它,输出是:
2> nvlink : info : Function properties for '_ZN3GPU4Flux4calcILj512EEEvv':
2> nvlink : info : used 23 registers, 216 stack, 15776 bytes smem, 320 bytes cmem[0], 0 bytes lmem
为什么当不使用\uuuu forceinline\uuu
时堆栈帧的大小会变小?
保持堆栈帧尽可能小有多重要?
谢谢您的帮助。减少堆栈帧的主要原因是堆栈分配在驻留在片外设备内存中的本地内存中。这使得对堆栈(如果没有缓存)的访问变慢 为了说明这一点,让我举一个简单的例子。考虑以下情况:
__device__ __noinline__ void func(float* d_a, float* test, int tid) {
d_a[tid]=test[tid]*d_a[tid];
}
__global__ void kernel_function(float* d_a) {
float test[16];
test[threadIdx.x] = threadIdx.x;
func(d_a,test,threadIdx.x);
}
请注意,\uuuuuu设备
功能已声明为\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在这种情况下
ptxas : info : Function properties for _Z15kernel_functionPf
64 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas : info : Used 7 registers, 36 bytes cmem[0]
i、 例如,我们有64个字节的堆栈帧。相应的反汇编代码为
MOV R1, c[0x1][0x100];
ISUB R1, R1, 0x40;
S2R R6, SR_TID.X; R6 = ThreadIdx.x
MOV R4, c[0x0][0x20];
IADD R5, R1, c[0x0][0x4];
I2F.F32.U32 R2, R6; R2 = R6 (integer to float conversion)
ISCADD R0, R6, R1, 0x2;
STL [R0], R2; stores R2 to test[ThreadIdx.x]
CAL 0x50;
EXIT ; __device__ function part
ISCADD R2, R6, R5, 0x2;
ISCADD R3, R6, R4, 0x2;
LD R2, [R2]; loads d_a[tid]
LD R0, [R3]; loads test[tid]
FMUL R0, R2, R0; d_a[tid] = d_a[tid]*test[tid]
ST [R3], R0; store the new value of d_a[tid] to global memory
RET ;
如您所见,test
存储并从全局内存加载,形成堆栈帧(它是16 floats=64字节
)
现在将设备功能更改为
__device__ __forceinline__ void func(float* d_a, float* test, int tid) {
d_a[tid]=test[tid]*d_a[tid];
}
也就是说,将\uuuuu设备
功能从\uuuuuuuuuoInline\uuuuuuuuu
更改为\uuuuuuuuuoForceInline\uuuuu
。在这种情况下,我们有
ptxas : info : Compiling entry function '_Z15kernel_functionPf' for 'sm_20'
ptxas : info : Function properties for _Z15kernel_functionPf
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
i、 例如,我们现在有一个空的堆栈帧。事实上,反汇编代码变成:
MOV R1, c[0x1][0x100];
S2R R2, SR_TID.X; R2 = ThreadIdx.x
ISCADD R3, R2, c[0x0][0x20], 0x2;
I2F.F32.U32 R2, R2; R2 = R2 (integer to float conversion)
LD R0, [R3]; R2 = d_a[ThreadIdx.x] (load from global memory)
FMUL R0, R2, R0; d_a[ThreadIdx.x] = d_a[ThreadIdx.x] * ThreadIdx.x
ST [R3], R0; stores the new value of d_a[ThreadIdx.x] to global memory
EXIT ;
如您所见,强制内联使编译器能够执行适当的优化,这样现在test
就从代码中完全丢弃了
在上面的例子中,\uuu forceinline\uuu
的效果与您所经历的相反,这也表明,没有任何进一步的信息,第一个问题无法回答。不可能回答第一个问题,因为您没有提供有关所涉及的\uuuu全局
和\uuu设备
功能的任何信息。第二个问题的答案可以给出,报告如下。有关如何获得有用答案的详细信息,请访问。引用CUDA标签信息:在你的问题中加入一个尽可能简单的代码示例,你就更有可能得到一个有用的答案。如果代码简短且自包含(因此用户可以自己测试),那就更好了。非常感谢您的解释。我没有发布代码的原因是它既长又复杂。对我来说有点奇怪的是,当我删除force_内联修饰符时,编译器减少了堆栈帧。后来我意识到我是在启用调试模式的情况下编译的。如果是这样,为什么不将强制内联定义为默认值,强制内联的缺点是什么