2017-08-16 20 views
-1

cublasDgemm()を使用して、行列の転置によって行列の積を計算しようとしています。入力行列と私は自分のコードから期待していた出力(それぞれAおよびC)は、次のとおりです。cublasDGemm奇妙な結果

| 1 4 7 |  | 66 78 | 
A = | 2 5 8 | C = | 78 93 | 

私は奇妙な結果を取得し、CUBLAS/CUDA寸法を理解することは私には少し難しいですが使用(列メジャー)。任意のヒントをいただければ幸いです!

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <cuda_runtime.h> 
#include "cublas_v2.h" 
#define M 3 
#define N 2 
#define IDX2C(i,j,ld) (((j)*(ld))+(i)) 

int main (void){ 
    cudaError_t cudaStat;  
    cublasStatus_t stat; 
    cublasHandle_t handle; 
    int i, j; 
    double *devPtrA, *devPtrC; 
    double *a = 0, *c = 0; 

    const double alpha = 1; 
    const double beta = 0; 

    // initialize host arrays 
    a = (double *)malloc (M * N * sizeof (*a)); 
    c = (double *)malloc (N * N * sizeof (*c)); 
    if (!a || !c) { 
     printf ("host memory allocation failed"); 
     return EXIT_FAILURE; 
    } 

    // fill input array 
    for (j = 0; j < N; j++) { 
     for (i = 0; i < M; i++) { 
      a[IDX2C(i,j,M)] = (double)(i * M + j + 1); 
      printf ("%7.0f", a[IDX2C(i,j,M)]); 
     } 
     printf ("\n"); 
    } 

    // set device to 0 (for double processing) 
    cudaStat = cudaSetDevice(0); 
    if (cudaStat != cudaSuccess) { 
     printf("could not set device 0"); 
     return EXIT_FAILURE; 
    } 

    // allocate device arrays 
    cudaStat = cudaMalloc ((void**)&devPtrA, M*N*sizeof(*a)); 
    if (cudaStat != cudaSuccess) { 
     printf ("device memory allocation of A failed"); 
     return EXIT_FAILURE; 
    } 
    cudaStat = cudaMalloc ((void**)&devPtrC, N*N*sizeof(*c)); 
    if (cudaStat != cudaSuccess) { 
     printf ("device memory allocation of C failed"); 
     return EXIT_FAILURE; 
    } 

    // create the cublas handle 
    stat = cublasCreate(&handle); 
    if (stat != CUBLAS_STATUS_SUCCESS) { 
     printf ("CUBLAS initialization failed\n"); 
     return EXIT_FAILURE; 
    } 

    // set the matrix a 
    stat = cublasSetMatrix (M, N, sizeof(*a), a, M, devPtrA, M); 
    if (stat != CUBLAS_STATUS_SUCCESS) { 
     printf ("data download failed"); 
     cudaFree (devPtrA); 
     cudaFree (devPtrC); 
     cublasDestroy(handle); 
     return EXIT_FAILURE; 
    } 

    stat = cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_T, M, M, N, &alpha, devPtrA, M, devPtrA, M, &beta, devPtrC, M); 
    if (stat!= CUBLAS_STATUS_SUCCESS) { 
     switch (stat) { 
      case CUBLAS_STATUS_NOT_INITIALIZED: 
       printf("CUBLAS_STATUS_NOT_INITIALIZED\n"); 
       break; 
      case CUBLAS_STATUS_INVALID_VALUE: 
       printf("CUBLAS_STATUS_INVALID_VALUE\n"); 
       break; 
      case CUBLAS_STATUS_ARCH_MISMATCH: 
       printf("CUBLAS_STATUS_ARCH_MISMATCH\n"); 
       break; 
      case CUBLAS_STATUS_EXECUTION_FAILED: 
       printf("CUBLAS_STATUS_EXECUTION_FAILED\n"); 
       break; 
      default: 
       printf("??\n"); 
     } 

     printf("Error: %d\n", (int)stat); 
     cudaFree (devPtrA); 
     cudaFree (devPtrC); 
     cublasDestroy(handle); 
     return EXIT_FAILURE; 
    } 

    // get matrix c 
    stat = cublasGetMatrix (N, N, sizeof(*c), devPtrC, N, c, N); 
    if (stat != CUBLAS_STATUS_SUCCESS) { 
     printf ("data upload failed"); 
     cudaFree (devPtrC); 
     cublasDestroy(handle); 
     return EXIT_FAILURE; 
    } 

    // cleanup cuda/cublas 
    cudaFree (devPtrA); 
    cudaFree (devPtrC); 
    cublasDestroy(handle); 

    // print result 
    for (j = 0; j < N; j++) { 
     for (i = 0; i < N; i++) { 
      printf ("%7.0f", c[IDX2C(i,j,M)]); 
     } 
     printf ("\n"); 
    } 

    // clear host data 
    free(a); 
    free(c); 
    return EXIT_SUCCESS; 
} 

答えて

2

最初の問題は、行列Aを行優先形式で埋めていることです。これを修正するには、単純にiとjのインデックスを入れ替えます。列優先フォーマットでは、主要な次元が行数である必要があり、あなたのケースでは、N.

for (j = 0; j < N; j++) { 
    for (i = 0; i < M; i++) { 
     a[IDX2C(j,i,N)] = (double)(i * M + j + 1); 
     printf ("%7.0f", a[IDX2C(j,i,N)]); 
    } 
    printf ("\n"); 
} 

ます。またcublasDgemmコールのディメンションを交換している、それは次のようになります。

stat = cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_T, N, N, M, &alpha, devPtrA, N, devPtrA, N, &beta, devPtrC, N); 

そして最後に、あなたはそれがNをされている必要がありますC行列の主要な次元としてMを使用:

printf ("%7.0f", c[IDX2C(i,j,N)]); 
+0

おかげでたくさんの男/小娘! upvotedと受け入れられる! – TheDillo