CUDA。数据组织

时间:2012-12-04 16:03:37

标签: cuda

在我的应用程序中,每个线程都需要它自己的数据矩阵。比方说,我有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]的元素xD[i][j](x) == A[T * (M * i + j) + x]

我的问题:计算复杂的索引计算成本很高。

P.S。我有Nvidia Tesla C2075(CUDA 2.0)。

1 个答案:

答案 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
}