【发布时间】:2019-04-05 12:14:17
【问题描述】:
对于我第一次尝试 CUDA/cuBLAS,我正在尝试编写一个简单的函数,它将 MxN 矩阵(用向量的向量,std::vector 表示)与 Nx1“ones”向量相乘,以便得到矩阵的行(?)总和。这将利用 cublas_gemv() 以及其他基本的 CUDA 操作,我认为这是一个很好的起点。
在处理了设置问题和阅读/复制示例代码之后,我得到了以下内容:
std::vector<double> test(std::vector<std::vector<double>> in)
{
std::vector<double> out;
long in_m = in.size();
long in_n = in[0].size();
cudaError_t cudaStat;
cublasStatus_t stat;
cublasHandle_t handle;
// This just converts a vector-of-vectors into a col-first array
double* p_in = vec2d_to_colfirst_array(in);
double* p_ones = new double[in_n];
double* p_out = new double[in_m];
std::fill(p_ones, p_ones + in_n, 1.0);
double* dev_in;
double* dev_ones;
double* dev_out;
cudaStat = cudaMalloc((void**)&dev_in, in_m * in_n * sizeof(double));
cudaStat = cudaMalloc((void**)&dev_ones, in_n * sizeof(double));
cudaStat = cudaMalloc((void**)&dev_out, in_m * sizeof(double));
stat = cublasCreate(&handle);
cudaStat = cudaMemcpy(dev_in, p_in, in_m*in_n * sizeof(double), cudaMemcpyHostToDevice);
cudaStat = cudaMemcpy(dev_ones, p_ones, in_n * sizeof(double), cudaMemcpyHostToDevice);
double alpha = 1.0;
double beta = 0.0;
stat = cublasDgemv(handle, CUBLAS_OP_N, in_m, in_n, &alpha, dev_in, in_m, dev_ones, 1, &beta, dev_ones, 1);
cudaStat = cudaMemcpy(p_out, dev_out, in_m * sizeof(double), cudaMemcpyDeviceToHost);
out.assign(p_out, p_out + in_m);
cudaFree(dev_in);
cudaFree(dev_ones);
cudaFree(dev_out);
cublasDestroy(handle);
free(p_in);
free(p_ones);
free(p_out);
return out;
}
它看起来与我阅读的示例没有太大不同,所以我希望它“正常工作”。但是,当我检查p_out 时,它全为零。当然我没有输入一个零 in 矩阵。
我验证了vec2d_to_colfirst_array() 的工作正常,并且dev_in/dev_ones 通过将数据从设备复制回主机然后读取来正确填充。也许问题出在对cublasDgemv() 的调用中,但由于我是新来的(而且与例如 Eigen 相比,BLAS 语法不那么直观),在经历了很多挫折之后,我看不出有什么问题。
任何帮助表示赞赏!
【问题讨论】:
-
stackoverflow.com/a/47755279/1231073。我猜你必须将指针模式设置为
CUBLAS_POINTER_MODE_HOST。 -
@sgarizvi: 这是 CUBLAS AFAIK 的默认设置
-
@talonmies.. 确实如此.....安迪,你能提供一个MCVE。