cublas 函数调用 cublasSgemv

Posted

技术标签:

【中文标题】cublas 函数调用 cublasSgemv【英文标题】:The cublas function call cublasSgemv 【发布时间】:2014-02-05 12:18:30 【问题描述】:

感谢@hubs,当调用 cublasSgemv 时应该注意到 CUBLAS_OP_T 也是转置向量。 /*我学习cuda和cublas一个月了,我想测试一下cublas的性能以备进一步使用。但是在我使用 cublasSgemv 的矩阵向量乘法中,答案是错误的。 我以行优先方式初始化矩阵 A 和向量 x。我使用 cudaMemcpy 将它们发送到设备,并调用函数 cublasSgemv ,因为 A 是行优先的,我使用参数 CUBLAS_OP_T 对其进行转置。*/

 //the row is 50,and col is 10, A[i]=i;x[i]=1; And A matrix is row major.
 //the answer I get is 45,545,.....4545,0,0,0,0,0,0,0,0,........0

int main()
int row=50;
int col=10;
int N=row*col;
float*A=new float[N];
float* y_gpu=new float[50]; 
for (int i=0;i<N;i++)

    A[i]=(float)i;

float* x=new float[10];
for (int i=0;i<10;i++)

    x[i]=1;

GpuVec(A,x,y_gpu,row,col);  //call the function 
    for(int i=0;i<50;i++)
    cout<<" "<<y_gpu[i]<<endl;  //
 

return 0;

int GpuVec(const float* A,const float* x, float* y,const int row,const int col)
cudaError_t cudastat;
cublasStatus_t stat;
int size=row*col;
cublasHandle_t handle;
float* d_A;  //device matrix
float* d_x;  //device vector
float* d_y;  //device result
cudastat=cudaMalloc((void**)&d_A,size*sizeof(float)); 
cudastat=cudaMalloc((void**)&d_x,col*sizeof(float));
cudastat=cudaMalloc((void**)&d_y,row*sizeof(float));// when I copy y to d_y ,can I cout d_y?

cudaMemcpy(d_A,A,sizeof(float)*size,cudaMemcpyHostToDevice);  //copy A to device d_A
cudaMemcpy(d_x,x,sizeof(float)*col,cudaMemcpyHostToDevice);   //copy x to device d_x
float alf=1.0;
float beta=0;
    stat=cublasCreate(&handle);
stat=cublasSgemv(handle,CUBLAS_OP_T,col,row,&alf,d_A,col,d_x,1,&beta,d_y,1);//swap col and row
cudaMemcpy(y,d_y,sizeof(float)*row,cudaMemcpyDeviceToHost); // copy device result to host 
cudaFree(d_A);
cudaFree(d_x);
cudaFree(d_y);
cublasDestroy(handle);
return 0;

【问题讨论】:

excact 是什么意思,答案是错误的?我认为您以错误的方式使用cublasSgemv。您使用CUBLAS_OP_T,这意味着您将使用d_A 的转置,这应该是数学错误。你有 A[col x raw] * x[col x 1] = y[row x 1] 这是错误的。 请提供完整的代码,包括对该函数的调用以及传递给它的所有变量。 正如您在cublas documentation 中所读到的,只有在使用CUBLAS_OP_N 时,x 才是由n(列)元素组成的向量。否则它有 m(行)个元素! 我编辑代码,谢谢@RobertCrovella A[rowcol] in c。但在 cublas 中它将是 A[colrow]。所以我转置A。对吗?@hubs 【参考方案1】:

要在 cublas 中使用以行优先顺序存储的二维数组(适用于列优先顺序),您可以通过这种方式调用 gemv

stat = cublasSgemv(handle, CUBLAS_OP_T, col, row, &alf, d_A, col, d_x, 1, &beta, d_y, 1);

您也必须在调用中交换 m(行)和 n(列)才能执行 y = A * x,但它允许您使用 cublas 调用而无需转置原始数组。

【讨论】:

谢谢。我复制你的代码,然后调用:cudaMemcpy(y,d_y,sizeof(float)*row,cudaMemcpyDeviceToHost);然后我 cout y[i] for i=0->row。结果的一半是 1.8628e+018,另一半是 18628035948437……我哪里出错了? 如果我只改变这一行,就像我上面写的那样,它对我有用。 我是编程新手。你认为它对我不起作用是什么? 1.8628e+018 与 18628035948437.... 相同,只是用指数表示。例如18628 = 1.8628e+004 我不会去猜测你在做什么。如果您发布一个完整的、可编译的代码来打印出数字(以不同的表示法),我可以看看。

以上是关于cublas 函数调用 cublasSgemv的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从全局或设备函数调用 CUDA CUBLAS 函数

异步 cuBLAS 调用

Cublas - 列/行明智的操作

cublas 函数的重叠输入和输出

cublas如何实现异步标量变量传输

自己写的cuda函数和cublas和ispc的对比(均支持非方阵的计算)