【发布时间】:2013-08-27 11:03:27
【问题描述】:
我正在为小输入数据(= 512 个元素)分析一个非常转储的排序算法。我正在调用一个从结构数组中读取合并的内核。
结构如下所示:
struct __align__(8) Elements
{
float weight;
int value;
};
nvprof 为 L1 未命中/命中和 gdl 指令提供以下指令计数:
Invocations Avg Min Max Event Name
Kernel: sort(Elements*)
500 0 0 0 gld_inst_8bit
500 0 0 0 gld_inst_16bit
500 1024 1024 1024 gld_inst_32bit
500 0 0 0 gld_inst_64bit
500 0 0 0 gld_inst_128bit
500 120 120 120 l1_global_load_hit
500 120 120 120 l1_global_load_miss
500 0 0 0 uncached_global_load_tr.
如果我改变结构的布局如下:
struct __align__(8) Elements
{
float weight;
float value;
};
分析输出如下所示:
Invocations Avg Min Max Event Name
Device 0
Kernel: sort(Elements*)
500 0 0 0 gld_inst_8bit
500 0 0 0 gld_inst_16bit
500 0 0 0 gld_inst_32bit
500 512 512 512 gld_inst_64bit
500 0 0 0 gld_inst_128bit
500 0 0 0 l1_global_load_hit
500 120 120 120 l1_global_load_miss
500 0 0 0 uncached_global_load_tr.
对执行时间没有任何影响,但我不明白为什么 GPU 在代码的第一个变体上执行 32 位加载指令而在第二个变体上执行 64 位指令。
内核使用 1 个块和 512 个线程调用(因此 l1_global_load_x 计数器可能不正确)。一切都在配备 CUDA 5.0 的 GeForce 480 上进行。
编辑: 排序内核(有点缩短):
__global__ void sort(Elements* nearest)
{
ThreadIndex idx = index();
__shared__ Elements temp[MAX_ELEMENTS];
__shared__ int index_cache[MAX_ELEMENTS];
temp[idx.x] = nearest[idx.x];
WeightedElements elem = temp[idx.x];
__syncthreads();
int c = 0;
// some index crunching
nearest[idx.x] = temp[c];
}
【问题讨论】:
-
可以添加你的内核代码吗?
-
GPU 在第一种情况下执行 32 位加载,因为编译器在这种情况下生成 32 位加载指令(在第二种情况下生成 64 位加载。)我猜你的问题是“为什么当我的结构依次具有两个
float类型时编译器会生成64 位加载,但是当我的结构有float后跟int时会加载两个32 位?
标签: cuda profiling instructions