MとNは数百になる可能性があるとあなたは言います。そのため、共有メモリをあまり使用できなくなります(あるとしても)。グローバルメモリ消費も注意深く監視できます(ただし、Teslaには大量のメモリがあります)。200x200 x 3584スレッド(私の意見では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
}