2011-04-05 10 views
6

CUDA를 사용하여 행렬 곱셈을 구현 한 후. 나는 CUBLAS (포럼의 일부 사람들의 조언 덕분에)로 구현하려고 시도했다.CUBLAS 행렬 곱셈

사각형 행렬을 곱할 수는 있지만 (다시 한 번 ...) 비 사각형 행렬로 작업하는 데 어려움이 있습니다. Matrix A의 너비 (A * B = C)가 다를 때 작동하는 비 정사각 행렬 곱셈의 유일한 유형입니다.

오류가 발생하지 않지만 결과 행렬이 잘못된 값을 반환합니다. 다음은 내 코드입니다 (기본적으로 simpleCUBLAS SDK 예제를 적용한 것입니다).

#include <stdlib.h> 
#include <stdio.h> 
#include "cublas.h" 
#define HA 2 
#define WA 9 
#define WB 2 
#define HB WA 
#define WC WB 
#define HC HA 
#define index(i,j,ld) (((j)*(ld))+(i)) 

void printMat(float*P,int uWP,int uHP){ 
//printf("\n %f",P[1]); 
int i,j; 
for(i=0;i<uHP;i++){ 

    printf("\n"); 

    for(j=0;j<uWP;j++) 
     printf("%f ",P[index(i,j,uHP)]); 
     //printf("%f ",P[i*uWP+j]); 
} 
} 




int main (int argc, char** argv) { 
    cublasStatus status; 
     int i,j; 
     cublasInit(); 

     float *A = (float*)malloc(HA*WA*sizeof(float)); 
     float *B = (float*)malloc(HB*WB*sizeof(float)); 
     float *C = (float*)malloc(HC*WC*sizeof(float)); 
    if (A == 0) { 
     fprintf (stderr, "!!!! host memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
    } 
    if (B == 0) { 
     fprintf (stderr, "!!!! host memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
    } 
    if (C == 0) { 
     fprintf (stderr, "!!!! host memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 


     for (i=0;i<HA;i++) 
    for (j=0;j<WA;j++) 
     A[index(i,j,HA)] = (float) index(i,j,HA); 
     for (i=0;i<HB;i++) 
    for (j=0;j<WB;j++) 
     B[index(i,j,HB)] = (float) index(i,j,HB); 
    /* 
    for (i=0;i<HA*WA;i++) 
    A[i]=(float) i; 
    for (i=0;i<HB*WB;i++) 
    B[i]=(float) i;   */ 


     float* AA; float* BB; float* CC; 

    /*ALLOCATE ON THE DEVICE*/ 
    status=cublasAlloc(HA*WA,sizeof(float),(void**)&AA); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 

     status=cublasAlloc(HB*WB,sizeof(float),(void**)&BB); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 

     status=cublasAlloc(HC*WC,sizeof(float),(void**)&CC); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 

    /*SET MATRIX*/ 
     status=cublasSetMatrix(HA,WA,sizeof(float),A,HA,AA,HA); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 

     status=cublasSetMatrix(HB,WB,sizeof(float),B,HB,BB,HB); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device memory allocation error (A)\n"); 
     return EXIT_FAILURE; 
     } 

    /*KERNEL*/ 
     cublasSgemm('n','n',HA,WB,WA,1,AA,HA,BB,HB,0,CC,HC); 

     status = cublasGetError(); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! kernel execution error.\n"); 
     return EXIT_FAILURE; 
     } 
     cublasGetMatrix(HC,WC,sizeof(float),CC,HC,C,HC); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! device read error (A)\n"); 
     return EXIT_FAILURE; 
     } 


    /* PERFORMANCE OUTPUT*/ 

    printf("\nMatriz A:\n"); 
    printMat(A,WA,HA); 
    printf("\nMatriz B:\n"); 
    printMat(B,WB,HB); 
    printf("\nMatriz C:\n"); 
    printMat(C,WC,HC); 

     free(A); free(B); free (C); 
     status = cublasFree(AA); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! memory free error (A)\n"); 
     return EXIT_FAILURE; 
     } 
     status = cublasFree(BB); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! memory free error (B)\n"); 
     return EXIT_FAILURE; 
     } 
     status = cublasFree(CC); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! memory free error (C)\n"); 
    return EXIT_FAILURE; 
    } 

     /* Shutdown */ 
     status = cublasShutdown(); 
     if (status != CUBLAS_STATUS_SUCCESS) { 
     fprintf (stderr, "!!!! shutdown error (A)\n"); 
     return EXIT_FAILURE; 
     } 

    if (argc > 1) { 
     if (!strcmp(argv[1], "-noprompt") ||!strcmp(argv[1], "-qatest")) 
     { 
    return EXIT_SUCCESS; 
     } 
     } 
     else 
     { 
      printf("\nPress ENTER to exit...\n"); 
      getchar(); 
     } 

return EXIT_SUCCESS; 


    } 

어떤 생각이 들었습니까? 또한, 누군가가 CUBLAS에서 작동하는 매트릭스 곱셈 구현을 가지고 있으므로 비교할 수 있습니까? 미리 감사드립니다.

+0

+1 용 cuBLAS'dgemm' 예 :-) – fommil

답변

7

내가 게시 한 코드가 작동하지 않는다고 생각하는 이유를 이해할 수 없습니다. 컴파일하고 실행할 때 matlab에 같은 행렬을 입력하고 그 결과를 계산하면 결과 출력은 동일한 출력을 생성합니다.

CUBLAS는 FORTRAN BLAS로, 주요 입력 순서로 입력을 기대합니다. 결과가 원하는 것과 일치하지 않으면 열과 행의 주요 순서를 어딘가에 혼동시켜야합니다.

+0

당신은 정말 옳았습니다;). 이전에 MATLAB (전공 칼럼)으로 작업해야했지만, 전공 행과 열의 주요 순서를 구별하지 않아도되었습니다. – Bernardo