内積の CUBLAS ルーチンを使用して 2 つのベクトルの内積を計算するコードを作成していますが、ホスト メモリに値が返されます。GPGPU のみでのさらなる計算に内積を使用したいと考えています。CPU から GPGPU への明示的なコピーを作成せずに、値を GPGPU のみに存在させ、それをさらなる計算に使用するにはどうすればよいですか?
2 に答える
「V2」APIを使用する限り、CUBLASでこれを行うことができます。新しい API にはcublasSetPointerMode
、スカラー値を返すすべてのルーチンにホスト ポインターではなくデバイス ポインターが渡されると想定するように API を設定するために使用できる関数が含まれています。これについては、最新の CUBLAS ドキュメントのセクション 2.4 で説明されています。例えば:
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <stdio.h>
int main(void)
{
const int nvals = 10;
const size_t sz = sizeof(double) * (size_t)nvals;
double x[nvals], y[nvals];
double *x_, *y_, *result_;
double result=0., resulth=0.;
for(int i=0; i<nvals; i++) {
x[i] = y[i] = (double)(i)/(double)(nvals);
resulth += x[i] * y[i];
}
cublasHandle_t h;
cublasCreate(&h);
cublasSetPointerMode(h, CUBLAS_POINTER_MODE_DEVICE);
cudaMalloc( (void **)(&x_), sz);
cudaMalloc( (void **)(&y_), sz);
cudaMalloc( (void **)(&result_), sizeof(double) );
cudaMemcpy(x_, x, sz, cudaMemcpyHostToDevice);
cudaMemcpy(y_, y, sz, cudaMemcpyHostToDevice);
cublasDdot(h, nvals, x_, 1, y_, 1, result_);
cudaMemcpy(&result, result_, sizeof(double), cudaMemcpyDeviceToHost);
printf("%f %f\n", resulth, result);
cublasDestroy(h);
return 0;
}
を使用CUBLAS_POINTER_MODE_DEVICE
すると、それがデバイス ポインターであるcublasDdot
と想定result_
され、結果をホストにコピーして戻す試みは行われません。これにより、ルーチンがdot
非同期のようになるため、デバイスとホスト間の同期に注意する必要があることに注意してください。
正確には、CUBLAS を使用することはできません。talonmies の回答によると、CUBLAS V2 API (CUDA 4.0) 以降では、戻り値をデバイス ポインターにすることができます。彼の答えを参照してください。しかし、V1 API を使用している場合、それは単一の値であるため、それを使用するカーネルに引数として渡すのは非常に簡単cudaMemcpy
です。 )。
Tesla K20 GPU および CUDA 5 以降では、CUDA 動的並列処理を使用してデバイス カーネルから CUBLAS ルーチンを呼び出すことができます。cublasSdot
これは、(たとえば) カーネル関数内から呼び出すことができることを意味__global__
し、結果は GPU に返されます。