记得之前ice或者是横扫千军曾经跟我讲过:
1:推荐尽量把工作都放在GPU上执行,避免来回copy数据。
2:把工作都放在GPU上执行也可以是CPU连续发射kernel,并非一定要GPU程序自己反复循环。
问题:1. 我对于CPU连续发射不太理解,能举个例子吗?
2. 另外,我的”矩阵求逆“和“矩阵相乘”用的都是CULA的库,我的显卡是Fermi构架,不支持GPU调用GPU函数,那这样的话,我只能在CPU端调用CULA库,这样就很难避免数据的来回copy啊!
楼主您好,
(1)根据当时对您说话的人的上下文,可能是指连续<<<>>>启动kernel。
(2)CULA是商业软件。请联系它们公司的技术支持。
1.连续启动,是下面这种情况吗?
for(int i=0;i<100;i++)
{
kernel<<<512,256>>>(A,i);
}
2.我下载的是CULA的免费版,好像里面只有6个常用的函数,我们导师没有花钱买它。我这样表达吧:假设不用CULA,就用自带的库cublas,里面也有矩阵相乘,这些库的矩阵相乘肯定比我写的优化的好,所以,有现成的库我想尽量利用现成的库。但是,这样的库只能在CPU端调用,也就是说就不能全部在GPU上运行了,怎么办呢?我的程序里面有很多的矩阵相乘,向量相乘,而且是在循环里面。
CULA我不懂,但是你说cublas在CPU端运行我不是很懂。
cublas库的函数参数基本都是GPU上的数据,只要你不把这些数据范虎拷回CPU,它就是一直在GPU上运行的。
比如:
for(int i=0;i<MAX;i++)
cublasSgemm(handle,……);
这样的写法,虽然看上去没有内核发射,像是CPU程序一样,实际上它里面封装了GPU内核发射程序。你这样写,它实际上就是完全在GPU上运行的。
是这样的,直接用cublasSgemm()算出的结果,跟CPU是不一样的,比如说,C=A*B,所以,我自己写了一个利用cublas库进行矩阵相乘的函数,这样,输出的结果就跟CPU的串行结果一致了。我并不是说矩阵相乘在CPU端运行,我是说在CPU端“调用”,不能再__global__里面调用,这样的话,岂不是需要在CPU与GPU间反复传递数据吗?(很有可能是我这样用是很笨的方法,如果有别的方法能达到目的也行,欢迎提建议~)我写的矩阵相乘如下:
void matMulmat(double *A,double *B,double *C,int M,int N,int K,const double alpha,const double beta) //矩阵相乘的CUBLAS库中的cublasDgemm()函数调用
{
int lda=N;
int ldb=K;
int ldc=N;
int m=N;
int n=M;
int k=K;
cublasOperation_t transa,transb;
transa=CUBLAS_OP_N;
transb=CUBLAS_OP_N;
size_t size_A=M*K*sizeof(double);
size_t size_B=K*N*sizeof(double);
size_t size_C=M*N*sizeof(double);
cublasStatus_t stat;
cudaError cudaStat;
cublasHandle_t handle;
stat=cublasCreate(&handle);
if(stat!=CUBLAS_STATUS_SUCCESS)
{
printf("CUBLAS initialization failed\n");
}
double *dev_A,*dev_B,*dev_C;
cudaStat=cudaMalloc((void**)&dev_A,size_B);
if(cudaStat!=cudaSuccess)
{
printf("Matrix A on device memory allocation failure!\n");
}
cudaStat=cudaMalloc((void**)&dev_B,size_A);
if(cudaStat!=cudaSuccess)
{
printf("Matrix B on device memory allocation failure!\n");
}
cudaStat=cudaMalloc((void**)&dev_C,size_C);
if(cudaStat!=cudaSuccess)
{
printf("Matrix C on device memory allocation failure!\n");
}
cudaStat=cudaMemcpy(dev_A,B,size_B,cudaMemcpyHostToDevice);
if(cudaStat!=cudaSuccess)
{
printf("Matrix from host(A) to device(dev_A) copy failure!\n");
}
cudaStat=cudaMemcpy(dev_B,A,size_A,cudaMemcpyHostToDevice);
if(cudaStat!=cudaSuccess)
{
printf("Matrix from host(B) to device(dev_B) copy failure!\n");
}
cublasDgemm(handle,transa,transb,m,n,k,&alpha,dev_A,lda,dev_B,ldb,&beta,dev_C,ldc);
if(stat!=CUBLAS_STATUS_SUCCESS)
{
printf("Function cublasDgemm() excute failure!\n");
cudaFree(dev_A);
cudaFree(dev_B);
cudaFree(dev_C);
cublasDestroy(handle);
}
cudaStat=cudaMemcpy(C,dev_C,size_C,cudaMemcpyDeviceToHost);
if(cudaStat!=cudaSuccess)
{
printf("Matrix from device(dev_C) to host(C) copy failure!\n");
}
cudaFree(dev_A);
cudaFree(dev_B);
cudaFree(dev_C);
cublasDestroy(handle);
}
“我自己写了一个利用cublas库进行矩阵相乘的函数,这样,输出的结果就跟CPU的串行结果一致了。
我并不是说矩阵相乘在CPU端运行,我是说在CPU端“调用”,不能再__global__里面调用,这样的话,岂不是需要在CPU与GPU间反复传递数据吗?”
楼主说这些您自己写的,那么是否每次都反复cudaMemcpy过来和过去不就是很清楚了吗?
既然是您自己写的东西,您如果在自己的kernel后每次都复制回来,并在下一次启动后并复制后去,那么自然您是知道的。您不需要反问我们。
反之,如果您自己写的那个kernel, 不需要反复复制结果回来又过去,您为何不简单的去掉呢?
我看不懂您的疑问所在。
LZ你看下这个主题http://cudazone.nvidia.cn/forum/forum.php?mod=viewthread&tid=6507的最后一楼,就知道怎么让cublas的矩阵相乘结果和CPU矩阵相乘结果对上了。
看来sdk里cublasMatrixMul的注释都没人看啊……
system
10
LZ您好,根据您5#的代码,您把malloc,copy,free神马的操作都包裹在里面了,请您仔细考虑您需要的行为和逻辑,看是否需要真的这么写,以及这是否是您的问题的来源。
祝您好运~
system
12
恕我直言,这不是灵活不灵活的问题,而是你有没有理解的问题。
你自己把copy(以及费时的malloc,free)都写到你的函数里面,然后抱怨copy太慢,效率低下。您在书写这个函数的时候,有搞清楚你需要的行为和你写出的行为一致么?
别人告诉你无需每次都copy,你有反思您的函数写法么?