很难理解如何在Cublas中组织数组(维度)。做了以下测试,但输出无法解释。谢谢你的帮助!
include <stdio.h>
include <stdlib.h>
include <cublas.h>
define DIMX 5
define DIMY 5
define ROW 2
define COL 3
typedef int TYPE;
void print_matrix(TYPE * v)
{
int i,j;
for (i=0; i<DIMX; i++)
{
for (j=0; j<DIMY; j++) printf("%5d ",v[i*DIMY+j]);
printf("\n");
}
}
int main()
{
printf("Hello world!\n");
int i;
//Initialize the array
TYPE v[DIMX*DIMY];
for (i=0; i<DIMX*DIMY; i++) v[i]=i+1;
printf("Before:\n");
print_matrix(v);
//Cublas part
cublasInit();
int *cv;
cublasAlloc(DIMX*DIMY,sizeof(TYPE),(void**)&cv);
cublasSetMatrix(ROW,COL,sizeof(TYPE),v,DIMX,cv,DIMY);
//cublasGetVector(DIMX*DIMY,sizeof(TYPE),cv,1,v,1);
cublasGetVector(DIMX*DIMY,sizeof(TYPE),cv,DIMX,v,DIMX);
cublasFree(cv);
cublasShutdown();
printf("After:\n");
print_matrix(v);
return 0;
}
输出:
你好世界! 之前: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 后: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
答案 0 :(得分:2)
您遇到的第一个问题是您没有进行错误检查。如果您正在进行错误检查,您会发现调用cublasGetVector时出现映射错误。其次,您需要查看cublas calls的API定义。在您对cublasSetMatrix的调用中,对于第一个矩阵的前导维度,您有DIMX和第二个矩阵的前导维度,您有DIMY。两者都应该是DIMX。由于您正在处理方形矩阵,因此这并不重要。您的cublasGetVector调用的问题在于您正在为inc参数传递DIMX和DIMY,这导致此复制操作超过GPU内存中矩阵cv的末尾。如果要根据ROW和COL参数捕获左上角元素,则应该为增量值传递1。这里有一些代码可以完成我认为您的意图,并显示错误检查的示例:
#include <stdio.h>
#include <stdlib.h>
#include <cublas.h>
#include <helper_cuda.h>
#define DIMX 5
#define DIMY 5
#define ROW 2
#define COL 3
typedef int TYPE;
#define cublasCheckErrors(fn) \
do { \
cublasStatus_t __err = fn; \
if (__err != CUBLAS_STATUS_SUCCESS) { \
fprintf(stderr, "Fatal error: %s (at %s:%d)\n", \
_cudaGetErrorEnum(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
void print_matrix(TYPE * v)
{
int i,j;
for (i=0; i<DIMX; i++)
{
for (j=0; j<DIMY; j++) printf("%5d ",v[i*DIMY+j]);
printf("\n");
}
}
int main()
{
printf("Hello world!\n");
int i;
//Initialize the array
TYPE v[DIMX*DIMY];
for (i=0; i<DIMX*DIMY; i++) v[i]=i+1;
printf("Before:\n");
print_matrix(v);
//Cublas part
cublasCheckErrors(cublasInit());
int *cv;
cublasCheckErrors(cublasAlloc(DIMX*DIMY,sizeof(TYPE),(void**)&cv));
cublasCheckErrors(cublasSetMatrix(ROW,COL,sizeof(TYPE),v,DIMX,cv,DIMX));
//cublasGetVector(DIMX*DIMY,sizeof(TYPE),cv,1,v,1);
cublasCheckErrors(cublasGetVector(DIMX*DIMY,sizeof(TYPE),cv,1,v,1));
cublasCheckErrors(cublasFree(cv));
cublasCheckErrors(cublasShutdown());
printf("After:\n");
print_matrix(v);
return 0;
}
您需要使用以下命令编译它:
g++ -I/usr/local/cuda/include -I /usr/local/cuda/samples/common/inc -L/usr/local/cuda/lib64 -lcublas -o t24 t24.cpp
这假设您有一个标准的CUDA 5安装,并且您在标准位置安装了cuda 5样本。这允许我为cublas选择一个方便的错误解析器:_cudaGetErrorEnum()
通过这些更改,我得到了这样的结果:
Hello world!
Before:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
After:
1 2 0 0 0
6 7 0 0 0
11 12 0 0 0
0 0 0 0 0
0 0 0 0 0
另请注意,您只是部分填充cv,但将cv的所有内容复制回v。这意味着我在After:结果中的上面有零,你可以有任何数字。所以你应该将cv的所有元素初始化为某个值。而我的After:结果显示2列和3行非零,因为虽然你有一个参数ROW,但是你将它传递给cublasSetMatrix调用上的错误位置。 cublas API通常期望以列为主的形式,这是行主要形式(典型的C或C ++形式)的索引的逆转。