我正在编写代码来使用点积的 CUBLAS 例程计算两个向量的点积,但它返回主机内存中的值。我只想使用点积在 GPGPU 上进行进一步计算。如何使值仅驻留在 GPGPU 上并将其用于进一步计算,而无需从 CPU 到 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
makecublasDdot
假设它result_
是一个设备指针,并且没有尝试将结果复制回主机。请注意,这会使例程像dot
异步一样,因此您可能需要密切关注设备和主机之间的同步。
确切地说,您不能使用 CUBLAS。根据 talonmies 的回答,从 CUBLAS V2 api (CUDA 4.0) 开始,返回值可以是设备指针。参考他的回答。但是如果你使用 V1 API,它是一个单一的值,所以将它作为参数传递给使用它的内核是非常简单的——你不需要显式的cudaMemcpy
(但是为了返回主机值,有一个隐含的)。
从 Tesla K20 GPU 和 CUDA 5 开始,您将能够使用 CUDA Dynamic Parallelism 从设备内核调用 CUBLAS 例程。这意味着您将能够cublasSdot
(例如)从__global__
内核函数内部调用,因此您的结果将在 GPU 上返回。