我编写了一个内核,用于计算给定D维向量q
(存储在常量存储器中)和N个向量(也是D维)的数组pts
之间的欧氏距离。
内存中的数组布局使得前N个元素是所有N个向量的第一个坐标,然后是N个第二个坐标的序列,依此类推。
这是内核:
__constant__ float q[20];
__global__ void compute_dists(float *pt, float *dst,
int n, int d) {
for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < n;
i += gridDim.x * blockDim.x) {
float ld = 0;
for (int j = 0; j < d; ++j) {
float tmp = (q[j] - pts[j * n + i]);
ld += tmp * tmp;
}
dst[i] = ld;
}
}r
调用如下:
const int N = 1000000, D = 20;
compute_dists<<<32, 512>>>(vecs, dists, vec, N, D);
现在,在Quadro K1000M上使用NVIDIA Visual Profiler分析此内核会导致警告
这对我来说非常令人惊讶,因为据我所知,内存访问是合并的
(因为j * n + i
总是32
的倍数,用于线程中的第一个warp,它给出了一个128字节的对齐方式)并且没有分支差异...
是否有一些其他因素导致指令重播开销指标,或者我错过了其他内容?
答案 0 :(得分:1)
我认为你有来自“pts [j * n + i]”的高TLB(Translation Lookaside Buffer)未命中率的问题。连续的第j个元素很可能不会出现在加载的内存页面中,因为 n 很大。 TLB硬件具有高延迟,用于加载给定存储器位置的页面所在的信息。这导致存储器加载指令重放。如果数据不在缓存中或者页面未加载到TLB中,则重新发出每个内存加载指令。虽然我对后者并不完全确定,但情况可能就是如此。希望能帮助到你。我有同样的问题,但有一个更严重的,97%的重播。 My question也可以回答你的问题。