我正在为小输入数据(= 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];
}