1

很难理解数组(维度)是如何在 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

4

1 回答 1

2

您遇到的第一个问题是您没有进行错误检查。如果您进行错误检查,您会发现调用 cublasGetVector 时出现映射错误。其次,您需要查看cublas 调用的 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++ 形式)的索引的反转。

于 2012-10-30T22:22:04.220 回答