Optimization CUDA代码中的cmem[2]使用量异常大
我正在CUDA上编写一个(公认的本地内存密集型)代码,我已经过了开发阶段,进入了加速阶段。命令行分析器表明我的占用率(我认为)非常低(主要内核为0.083-0.417),我希望对此进行改进。不幸的是,计算工作需要大量的Optimization CUDA代码中的cmem[2]使用量异常大,optimization,cuda,gpu,Optimization,Cuda,Gpu,我正在CUDA上编写一个(公认的本地内存密集型)代码,我已经过了开发阶段,进入了加速阶段。命令行分析器表明我的占用率(我认为)非常低(主要内核为0.083-0.417),我希望对此进行改进。不幸的是,计算工作需要大量的\uuuuu共享\uuuuu内存(每128个线程块16-20 kB)和一些寄存器(主要内核报告为63,尽管我不确定我是否实际使用了这么多…) 不过,我真正的问题是关于cmem[2]。下面是一个例子: 使用了8个寄存器,40字节cmem[0],51584字节cmem[2],368字节
\uuuuu共享\uuuuu
内存(每128个线程块16-20 kB)和一些寄存器(主要内核报告为63,尽管我不确定我是否实际使用了这么多…)
不过,我真正的问题是关于cmem[2]
。下面是一个例子:
使用了8个寄存器,40字节cmem[0],51584字节cmem[2],368字节cmem[14],4字节cmem[16]
所有内核似乎都使用了大量的cmem[2]
,我甚至不确定它是什么。我通过通常的cudamaloc
调用在设备上存储了大量内存,并通过cudaMemcpyToSymbol
调用在\uuuu constant\uuuuuu
内存中存储了少量的双精度和指针(虽然没有接近50KB),但仅此而已。所以我的问题是:我究竟如何使用所有这些cmem[2]
,它是否限制了我的内核占用率
另外,我正在运行GTX550TI,CUDA4.2和Ubuntu 10.04.4 64位。nvcc生成的可执行文件被包装在mpirun中,因为代码也是MPI并行的。在费米体系结构上,CUDA驱动程序使用cmem[2]存储常量变量。同一模块中的所有函数共享相同的常量。这个固定银行的规模不会影响您的理论SM占用率或增加您的启动开销。如果超过最大大小(64KB),则会收到编译器错误 CUDA二进制实用程序cuobjdump可用于调试分配 如果文件sm20.cu具有以下常量
__constant__ float k_float_array[] = { 0.f, 1.f, 2.f, 3.f };
__constant__ double k_double_array[] = { 0.0, 1.0, 2.0, 3.0 };
__constant__ int k_int_array[] = { 0, 1, 2, 3 };
__global__ void empty_kernel(float* a)
{
return;
}
你可以跑
cuobjdump.exe -elf sm20.cu.obj
可执行文件也可以用作参数。运行cuobjdump——帮助获取选项列表
此命令将产生以下输出
Fatbin elf code:
================
arch = sm_20
code version = [1,5]
producer = cuda
host = windows
compile_size = 32bit
identifier = c:/dev/constant/sm20.cu
32bit elf: abi=5, sm=20, flags = 0x140114
Sections:
Index Offset Size ES Align Type Flags Link Info Name
1 34 a6 0 1 STRTAB 0 0 0 .shstrtab
2 da e9 0 1 STRTAB 0 0 0 .strtab
3 1c4 80 10 4 SYMTAB 0 2 6 .symtab
4 244 18 0 4 CUDA_INFO 0 3 0 .nv.info
5 25c 20 0 4 CUDA_INFO 0 3 8 .nv.info._Z12empty_kernelPf
6 27c 24 0 4 PROGBITS 2 0 8 .nv.constant0._Z12empty_kernelPf
7 2a0 40 0 8 PROGBITS 2 0 0 .nv.constant2
8 2e0 10 0 4 PROGBITS 6 3 2000007 .text._Z12empty_kernelPf
elf节.nv.constant2包含cmem[2]的内容。此大小为0x40==64字节,符合我的预期
.nv.constant2是第7节索引
.section .strtab
.section .shstrtab
.section .symtab
index value size info other shndx name
0 0 0 0 0 0 (null)
1 0 0 3 0 8 .text._Z12empty_kernelPf
2 0 0 3 0 6 .nv.constant0._Z12empty_kernelPf
3 0 0 3 0 7 .nv.constant2
4 0 16 1 0 7 k_float_array
5 16 32 1 0 7 k_double_array
6 48 16 1 0 7 k_int_array
7 0 16 12 10 8 _Z12empty_kernelPf
.symtab包含定义的3个常量数组。shndx==7的所有符号都将位于.nv.constant2中
.nv.constant0._Z12empty_kernelPf
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000
.nv.constant2
0x00000000 0x3f800000 0x40000000 0x40400000 0x00000000
0x00000000 0x00000000 0x3ff00000 0x00000000
0x40000000 0x00000000 0x40080000 0x00000000
0x00000001 0x00000002 0x00000003
.nv.constant2定义节中的二进制数据。这与声明的常量变量相匹配。如果有很多常量,.symtab部分会标识每个符号的偏移量和大小
// skipping .nv.info and .text
cuobjdump可用于转储PTX和SASS代码。PTX和SASS汇编可用于确定哪些内核使用常量。在费米体系结构上,CUDA驱动程序使用cmem[2]存储常量变量。同一模块中的所有函数共享相同的常量。这个固定银行的规模不会影响您的理论SM占用率或增加您的启动开销。如果超过最大大小(64KB),则会收到编译器错误 CUDA二进制实用程序cuobjdump可用于调试分配 如果文件sm20.cu具有以下常量
__constant__ float k_float_array[] = { 0.f, 1.f, 2.f, 3.f };
__constant__ double k_double_array[] = { 0.0, 1.0, 2.0, 3.0 };
__constant__ int k_int_array[] = { 0, 1, 2, 3 };
__global__ void empty_kernel(float* a)
{
return;
}
你可以跑
cuobjdump.exe -elf sm20.cu.obj
可执行文件也可以用作参数。运行cuobjdump——帮助获取选项列表
此命令将产生以下输出
Fatbin elf code:
================
arch = sm_20
code version = [1,5]
producer = cuda
host = windows
compile_size = 32bit
identifier = c:/dev/constant/sm20.cu
32bit elf: abi=5, sm=20, flags = 0x140114
Sections:
Index Offset Size ES Align Type Flags Link Info Name
1 34 a6 0 1 STRTAB 0 0 0 .shstrtab
2 da e9 0 1 STRTAB 0 0 0 .strtab
3 1c4 80 10 4 SYMTAB 0 2 6 .symtab
4 244 18 0 4 CUDA_INFO 0 3 0 .nv.info
5 25c 20 0 4 CUDA_INFO 0 3 8 .nv.info._Z12empty_kernelPf
6 27c 24 0 4 PROGBITS 2 0 8 .nv.constant0._Z12empty_kernelPf
7 2a0 40 0 8 PROGBITS 2 0 0 .nv.constant2
8 2e0 10 0 4 PROGBITS 6 3 2000007 .text._Z12empty_kernelPf
elf节.nv.constant2包含cmem[2]的内容。此大小为0x40==64字节,符合我的预期
.nv.constant2是第7节索引
.section .strtab
.section .shstrtab
.section .symtab
index value size info other shndx name
0 0 0 0 0 0 (null)
1 0 0 3 0 8 .text._Z12empty_kernelPf
2 0 0 3 0 6 .nv.constant0._Z12empty_kernelPf
3 0 0 3 0 7 .nv.constant2
4 0 16 1 0 7 k_float_array
5 16 32 1 0 7 k_double_array
6 48 16 1 0 7 k_int_array
7 0 16 12 10 8 _Z12empty_kernelPf
.symtab包含定义的3个常量数组。shndx==7的所有符号都将位于.nv.constant2中
.nv.constant0._Z12empty_kernelPf
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000
.nv.constant2
0x00000000 0x3f800000 0x40000000 0x40400000 0x00000000
0x00000000 0x00000000 0x3ff00000 0x00000000
0x40000000 0x00000000 0x40080000 0x00000000
0x00000001 0x00000002 0x00000003
.nv.constant2定义节中的二进制数据。这与声明的常量变量相匹配。如果有很多常量,.symtab部分会标识每个符号的偏移量和大小
// skipping .nv.info and .text
cuobjdump可用于转储PTX和SASS代码。PTX和SASS汇编可用于确定哪些内核正在使用常量。您是否查看了内核编译的PTX输出(
nvcc-PTX
)?这可能会给你一些提示。你的内核有很多参数还是复杂的结构参数?你能提供至少一个cmem使用量大的内核的原型吗?还有用于编译的nvcc命令行。您看过内核编译的PTX输出了吗(nvcc-PTX
)?这可能会给你一些提示。你的内核有很多参数还是复杂的结构参数?你能提供至少一个cmem使用量大的内核的原型吗?还有用于编译的nvcc命令行。