カーネルがグローバル メモリに何度も移動する必要がある 1 つの CUDA アプリを開発しています。このメモリは、すべての CTA によってランダムにアクセスされます (ローカリティがないため、共有メモリを使用できません)。最適化する必要があります。テクスチャ メモリがこの問題を軽減すると聞きましたが、カーネルはテクスチャ メモリに読み書きできますか? 1D テクスチャ メモリ? 2D テクスチャ メモリ? また、CUDA配列はどうですか?
5 に答える
CUDAテクスチャは読み取り専用です。テクスチャ読み取りはキャッシュされます。したがって、パフォーマンスの向上は確率的です。
CUDA Toolkit 3.1以降には、Surfacesと呼ばれる書き込み可能なテクスチャもありますが、これらはCompute Capability>=2.0のデバイスでのみ使用できます。サーフェスはテクスチャと同じですが、カーネルで記述できるという利点があります。
cudaArray
サーフェスは、フラグを使用して作成するようにバインドすることしかできませんcudaArraySurfaceLoadStore
。
これは、sgarizvi の回答のフォローアップです。
現在、コンピューティング機能を備えたカードは、この質問が行われた当時>=2.0
よりもはるかに一般的です。2012
以下は、 CUDA サーフェス メモリを使用してtextureに書き込む方法の最小限の例です。
#include <stdio.h>
#include "TimingGPU.cuh"
#include "Utilities.cuh"
surface<void, cudaSurfaceType1D> surfD;
/*******************/
/* KERNEL FUNCTION */
/*******************/
__global__ void SurfaceMemoryWrite(const int N) {
int tid = blockIdx.x * blockDim.x + threadIdx.x;
surf1Dwrite((float)tid, surfD, tid * sizeof(float), cudaBoundaryModeTrap);
}
/********/
/* MAIN */
/********/
int main() {
const int N = 10;
cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
//Alternatively
//cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);
cudaArray *d_arr; gpuErrchk(cudaMallocArray(&d_arr, &channelDesc, N, 1, cudaArraySurfaceLoadStore));
gpuErrchk(cudaBindSurfaceToArray(surfD, d_arr));
SurfaceMemoryWrite<<<1, N>>>(N);
float *h_arr = new float[N];
gpuErrchk(cudaMemcpyFromArray(h_arr, d_arr, 0, 0, N * sizeof(float), cudaMemcpyDeviceToHost));
for (int i=0; i<N; i++) printf("h_arr[%i] = %f\n", i, h_arr[i]);
return 0;
}
私はあなたの記憶をピッチ線形記憶として宣言し、テクスチャをバインドすることをお勧めします。新しいバインドレステクスチャはまだ試していません。誰もがそれを試しましたか?
前述のテクスチャメモリは、キャッシュを介した読み取り専用です。読み取り専用メモリとして扱います。したがって、カーネル自体の内部では、テクスチャキャッシュに更新されない可能性があるため、テクスチャにバインドされたメモリに書き込みを行わないことに注意することが重要です。