2

sizeの 1D 配列にフラット化された各次元srcの sizeの 3D 配列をカーネルに送信し、結果を計算して に格納したいと思います。ただし、最後に不適切にすべて 0 が含まれます。これが私のコードです:sizelength = size * size * sizedstdst

int size = 256;
int length = size * size * size;
int bytes = length * sizeof(float);

// Allocate source and destination arrays on the host and initialize source array

float *src, *dst;
cudaMallocHost(&src, bytes);
cudaMallocHost(&dst, bytes);
for (int i = 0; i < length; i++) {
    src[i] = i;
}

// Allocate source and destination arrays on the device

struct cudaPitchedPtr srcGPU, dstGPU;
struct cudaExtent extent = make_cudaExtent(size*sizeof(float), size, size);
cudaMalloc3D(&srcGPU, extent);
cudaMalloc3D(&dstGPU, extent);

// Copy to the device, execute kernel, and copy back to the host

cudaMemcpy(srcGPU.ptr, src, bytes, cudaMemcpyHostToDevice);
myKernel<<<numBlocks, blockSize>>>((float *)srcGPU.ptr, (float *)dstGPU.ptr);
cudaMemcpy(dst, dstGPU.ptr, bytes, cudaMemcpyDeviceToHost);

cudaMallocHost()cudaMalloc()およびcudaMemcpy()明確にするために、のエラーチェックを省略しました。いずれの場合も、このコードによってトリガーされるエラーはありません。

cudaMalloc3D()withの正しい使い方は何cudaMemcpy()ですか?

カーネルの最小限のテスト ケースも投稿する必要があるかどうか、または上記のコードで問題が見つかるかどうかをお知らせください。

4

1 に答える 1

3

編集: エクステントは、CUDA 配列を使用している場合は要素数を取りますが、CUDA 配列を使用していない場合は事実上バイト数を取ります (たとえば、 の非配列バリアントで割り当てられたメモリcudaMalloc)

ランタイム API CUDA ドキュメントから:

extent フィールドは、転送された領域の寸法を要素で定義します。CUDA 配列がコピーに参加している場合、範囲はその配列の要素に関して定義されます。CUDA 配列がコピーに参加していない場合、エクステントはunsigned charの要素で定義されます

また、ピッチcudaMalloc3Dポインターを返します。つまり、少なくとも指定したエクステントのディメンションを持ちますが、配置上の理由からそれ以上になる可能性があります。デバイスのメモリにアクセスしてコピーするときは、このピッチを考慮する必要があります。構造体のドキュメントについては、こちらを参照してくださいcudaPitchedPtr

cudaMalloc3Dwithの使用についてcudaMemcpyは、 using cudaMemcpy3D(ドキュメントはこちら) を参照してください。ホストとデバイスのメモリのピッチを考慮すると、作業が少し楽になるかもしれません。使用するには、適切な情報を含む構造体cudaMemcpy3Dを作成する必要があります。cudaMemcpy3DParmsそのメンバーは次のとおりです。

cudaArray_t dstArray
struct cudaPos dstPos
struct cudaPitchedPtr dstPtr
struct cudaExtent extent
enumcudaMemcpyKind kind
cudaArray_t srcArray
struct cudaPos srcPos
struct cudaPitchedPtr srcPtr

また、またはの 1 つとsrcArray または の 1つを指定する必要があります。また、ドキュメントでは、構造体を使用する前に構造体を 0 に初期化することを推奨しています。 srcPtrdstArray dstPtrcudaMemcpy3DParms myParms = {0};

また、この他のSOの質問を見ることに興味があるかもしれません

于 2013-05-15T18:14:05.843 に答える