1

JavaでCudaを使用する方法を理解しようとしています。jCudaを使用しています。

コードを含む例に出くわすまで、すべて問題ありませんでした:

    // Set up the kernel parameters: A pointer to an array
    // of pointers which point to the actual values.
    Pointer kernelParameters = Pointer.to(
        Pointer.to(new int[]{numElements}),
        Pointer.to(deviceInputA),
        Pointer.to(deviceInputB),
        Pointer.to(deviceOutput)
    );

カーネル関数のプロトタイプは次のとおりです。

__global__ void add(int n, float *a, float *b, float *sum)

問題は 、c に関しては、次のようなものを渡しているように見えませんか?

(***n, ***a, ***b, ***sum)

つまり、基本的に、常に次のものが必要ですか。

Pointer kernelParameters = Pointer.to( double pointer, double pointer, ...)???

ありがとうございました

4

1 に答える 1

3

cuLaunchKernelJCudacuLaunchKernel機能は CUDAの機能に対応しています。CUDA でのこの関数のシグネチャは次のとおりです。

CUresult cuLaunchKernel(
    CUfunction f, 
    unsigned int gridDimX, 
    unsigned int gridDimY, 
    unsigned int gridDimZ, 
    unsigned int blockDimX, 
    unsigned int blockDimY, 
    unsigned int blockDimZ, 
    unsigned int sharedMemBytes, 
    CUstream hStream, 
    void** kernelParams, 
    void** extra) 

ここで、kernelParamsこの質問に関連する唯一のパラメーターです。ドキュメントによると

カーネル パラメータは で指定できますkernelParamsfN 個のパラメーターがある場合はkernelParams、N 個のポインターの配列である必要があります。kernelParams[0]~のそれぞれはkernelParams[N-1]、実際のカーネル パラメータがコピーされるメモリ領域を指している必要があります。


ここで重要な点は、最後の文です。kernelParams配列の要素は、実際のカーネル パラメータではありません。それらは実際のカーネルパラメーターのみを指します。

実際、これには奇妙な効果があり、単一の を受け取るカーネルのfloat *pointer場合、基本的に次のようにカーネルパラメーターを設定できます。

float *pointer= allocateSomeDeviceMemory();
float** pointerToPointer = &pointer;
float*** pointerToPointerToPointer = &pointerToPointer;
void **kernelParams = pointerToPointerToPointer;

(これは、これが実際にポインタへのポインタへのポインタであることを明確にするためのものです。実際には、そのようには書きません)


現在、カーネルパラメーターの「構造」は、JCuda と CUDA で基本的に同じです。もちろんJavaでは「ポインタのアドレス」は取れませんが、間接の数は同じです。次のようなカーネルがあるとします。

__global__ void example(int value, float *pointer)

CUDA C API では、カーネル パラメーターを次のように定義できます。

int value = 123;
float *pointer= allocateSomeDeviceMemory();

int* pointerToValue = &value;
float** pointerToPointer = &pointer;

void **kernelParams = {
    pointerToValue,
    pointerToPointer
};

セットアップは、JCuda Java API で同様に行われます。

int value = 123;
Pointer pointer= allocateSomeDeviceMemory();

Pointer pointerToValue = Pointer.to(new int[]{value});
float** pointerToPointer = Pointer.to(pointer);

Pointer kernelParameters = Pointer.to(
    pointerToValue,
    pointerToPointer
);

ここで重要な主な違いは、アドレス演算子を使用して C でこれをもう少し簡潔に記述できることです&

void **kernelParams = {
    &value,             // This can be imagined as a pointer to an int
    &pointer            // This can be imagined as a pointer to a pointer
};

しかし、これは基本的にあなたが提供した例と同じです:

Pointer kernelParameters = Pointer.to(
    Pointer.to(new int[]{value}),   // A pointer to an int
    Pointer.to(pointer)             // A pointer to a pointer
);

繰り返しますが、重要なポイントは、

void **kernelParams = {
    &value,
};

また

Pointer kernelParameters = Pointer.to(
    Pointer.to(new int[]{value}),
);

valueカーネルに直接渡していません。代わりに、CUDA に次のように伝えていintます。

于 2015-12-30T17:10:18.317 に答える