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 22 23 24 25

4

1 に答える 1

2

最初の問題は、エラー チェックを行っていないことです。エラー チェックを行っていた場合、cublasGetVector への呼び出しでマッピング エラーが発生することがわかります。次に、cublas 呼び出しの API 定義を確認する必要があります。. cublasSetMatrix への呼び出しでは、最初の行列の最初の次元には DIMX があり、2 番目の行列の最初の次元には 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: 結果は、パラメーター ROW を持っていますが、cublasSetMatrix 呼び出しで間違った位置に渡しているため、ゼロ以外の 2 列と 3 行を示しています。cublas API は一般に、行優先の形式 (典型的な C または C++ 形式) からのインデックスの反転である列優先の形式で物事を想定しています。

于 2012-10-30T22:22:04.220 に答える