在我的应用程序中,每个线程都需要它自己的数据矩阵。比方说,我有T
个线程,每个线程使用不同的矩阵D[M][N]
。
我的问题:如何组织数据结构?
我的解决方案:我定义了A
元素的数组T*M*N
。为了避免银行冲突,我首先为每个帖子存储元素D[0][0]
T
次,然后D[0][1]
... D[0][M-1]
,D[1][0]
等等(如果你看看这个数组就像在矩阵T * (M*N)
一样,每个线程都有一列。通过这种方式,我对不同存储体中的不同线程具有相同的元素。相应地,我通过以下方式访问线程D[i][j]
的元素x
:D[i][j](x) == A[T * (M * i + j) + x]
。
我的问题:计算复杂的索引计算成本很高。
P.S。我有Nvidia Tesla C2075(CUDA 2.0)。
答案 0 :(得分:0)
你说M和N可以是几百。为此,您将无法使用共享内存(如果有的话)。您也可以仔细观察全球内存消耗(虽然特斯拉有很多内存)! 200x200 x 3584threads(在我看来是C2075的最低限度)x sizeof(int) - 这使得547MB的数据。
全局内存访问模式的工作方式不同。全局内存分为32,64和128B的段。读取的成本大约是每个经线的不同段访问的数量。简而言之,它通常归结为 - 您的访问权限越多 - 越糟糕。
因此,除非每个线程在相同的索引处访问自己的矩阵(至少在大多数时间),否则没有内存组织会有效。但是,如果上述情况属实 - 那么您描述的布局可能会有效。
此外,如果您有扩展访问模式,禁用L1缓存可能会有所帮助。这是因为L1缓存行为128B,但L2仅为32B - 因此您可以减少过度获取。至少 - 尝试一下:))
为了减轻访问数组的痛苦,我会做这样的事情:
//let the kernel dimentions be known at compile time - you can safe some computation and registers
//assuming one-dimentional kernels
static const int blockSize = ...; //equivalent to blockDim
static const int gridSize = ...; //equivalent to gridDim
static const int rowSize = blockSize * gridSize;
template <typename T, int M, int N>
class MyMatrix {
private:
T* data; //flattened array in global memory
int tid;
public:
__device__ inline MyMatrix(T* dataIsHere) : data(dataIsHere) {
tid = threadIdx.x+blockDim.x*blockIdx.x;
}
__device__ inline T& operator()(int x, int y) {
return data[(y*M+x)*rowSize+tid];
}
}
//assuming the matrix size is 200x200 and consists of ints:
__global__ void myKernel(int* flattenedMatrices) {
MyMatrix<int,200,200> matrix(flattenedMatrices);
...
matrix(2,4) = .... // happily access the matrix for both loads and stores
}