为什么cublasGetVector得到这个结果?

时间:2012-10-30 17:41:59

标签: cuda cublas

很难理解如何在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

1 个答案:

答案 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 ++形式)的索引的逆转。