【发布时间】:2013-02-16 17:35:51
【问题描述】:
我的内核使用 float 大小为 8 x 8 的数组,下面是随机访问模式。
// inds - big array of indices in range 0,...,7
// flts - 8 by 8 array of floats
// kernel essentially processes large 2D array by looping through slow coordinate
// and having block/thread parallelization of fast coordinate.
__global__ void kernel (int const* inds, float const* flt, ...)
{
int idx = threadIdx.x + blockDim.x * blockIdx.x; // Global fast coordinate
int idy; // Global slow coordinate
int sx = gridDim.x * blockDim.x; // Stride of fast coordinate
for ( idy = 0; idy < 10000; idy++ ) // Slow coordinate loop
{
int id = idx + idy * sx; // Global coordinate in 2D array
int ind = inds[id]; // Index of random access to small array
float f0 = flt[ind * 8 + 0];
...
float f7 = flt[ind * 8 + 7];
NEXT I HAVE SOME ALGEBRAIC FORMULAS THAT USE f0, ..., f7
}
}
访问flt 数组的最佳方式是什么?
- 不要通过
flt,使用__const__内存。我不确定当不同线程访问不同数据时 const 内存有多快。 - 如上使用。不会使用负载统一,因为线程访问不同的数据。由于缓存,它会很快吗?
- 复制到共享内存并使用共享内存数组。
- 使用纹理。从未使用过纹理...这种方法能很快吗?
对于共享内存,转置flt 数组可能会更好,即以这种方式访问它以避免银行冲突:
float fj = flt_shared[j * 8 + ind]; // where j = 0, ..., 7
PS:目标架构是 Fermi 和 Kepler。
【问题讨论】:
-
那么,您是否尝试过使用
__constant__或__shared__内存并为内核计时?flt在内核中被多次访问。我认为__shared__内存会给你最好的性能。 -
__constant__只有当一个 warp 中的所有线程都可以访问相同的值时才会是一个不错的选择,而这里的情况并非如此。恕我直言,这里最好的选择是使用包含转置数据的共享内存。请指定您的目标计算架构,它可能会产生影响。 -
到目前为止,我只实现了
inds数组中所有值都为0的情况,所以我没有随机访问,我使用__const__内存而不是flt参数。顺便说一句,在这种情况下,如果使用-dlcm=cg选项编译,我的内核工作得更快。现在我需要将我的内核扩展到一般情况。