Cuda 使用CUBLAS例程在GPGPU上保留点积

Cuda 使用CUBLAS例程在GPGPU上保留点积,cuda,gpgpu,cublas,dot-product,Cuda,Gpgpu,Cublas,Dot Product,我正在编写一个代码,使用点积的CUBLAS例程计算两个向量的点积,但它返回主机内存中的值。我只想在GPGPU上使用点积进行进一步的计算。如何使该值仅驻留在GPGPU上,并将其用于进一步的计算,而不从CPU显式复制到GPGPU?确切地说,您不能使用CUBLAS。根据Talonmes的回答,从CUBLAS V2 api CUDA 4.0开始,返回值可以是设备指针。参考他的答案。但是如果您使用的是v1api,那么它是一个单一的值,因此将它作为参数传递给使用它的内核是非常简单的,您不需要显式的cudaM

我正在编写一个代码,使用点积的CUBLAS例程计算两个向量的点积,但它返回主机内存中的值。我只想在GPGPU上使用点积进行进一步的计算。如何使该值仅驻留在GPGPU上,并将其用于进一步的计算,而不从CPU显式复制到GPGPU?

确切地说,您不能使用CUBLAS。根据Talonmes的回答,从CUBLAS V2 api CUDA 4.0开始,返回值可以是设备指针。参考他的答案。但是如果您使用的是v1api,那么它是一个单一的值,因此将它作为参数传递给使用它的内核是非常简单的,您不需要显式的cudaMemcpy,但是为了返回主机值,有一个隐含的cudaMemcpy


从特斯拉K20 GPU和CUDA5开始,您将能够使用CUDA动态并行从设备内核调用CUBLAS例程。这意味着您可以从uu global uuu内核函数内部调用cublasSdot,因此您的结果将在GPU上返回。

您可以在CUBLAS中执行此操作,只要使用V2 API即可。较新的API包含一个函数CublessPointerMode,您可以使用该函数设置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_设备会使cublasDdot假定result_是设备指针,并且不会尝试将结果复制回主机。请注意,这使得像点这样的例程是异步的,所以您可能需要关注设备和主机之间的同步。

Mark,这不是真的。由于CUBLAS 4.0或V2 API发布时,结果参数可以是主机或设备指针,调用将很高兴地将结果保留在设备内存中。感谢您的更正。本可以给我时间编辑我的答案,但时区差异很大