умножение строк на старшие кубы - PullRequest
0 голосов
/ 08 мая 2019

Я пытаюсь использовать cublasSgemm для умножения двух неквадратных матриц, которые хранятся в главном порядке строк. Я знаю, что у этой функции есть один параметр, в котором вы можете указать, что если вы хотите транспонировать матрицы (CUBLAS_OP_T), но результат сохраняется в мажорном столбце, а мне он нужен и в мажорной строке.

Кроме того, мой код не способен умножать неквадратные матрицы с параметром CUBLAS_OP_T. Только квадрат или не квадрат с CUBLAS_OP_N.

Кроме того, я знаю, что есть возможность объявить матрицы в порядке столбцов с

define IDX2C(i,j,ld) (((j)*(ld))+(i)) 

но это не вариант, потому что матрицы, которые я должен использовать, будут установлены в другой программе.

Полагаю, в интернете много информации, но я не могу найти ответ на свой вопрос.

мой код следующий:


    int m = 2;
    int k = 3;
    int n = 4;
    int print = 1;
    cudaError_t cudaStat; // cudaMalloc status
    cublasStatus_t stat; // CUBLAS functions status
    cublasHandle_t handle; // CUBLAS context

    int i,j;

    float *a, *b,*c;

    //malloc for a,b,c...

    // define a mxk matrix a row by row
    int ind =11;                               
    for(j=0;j<m*k;j++){                     
        a[j]=(float)ind++;                                    
    }                                        

    // define a kxn matrix b column by column
    ind =11;                               
    for(j=0;j<k*n;j++){                     
        b[j]=(float)ind++;                                    
    }                                        


    // DEVICE
    float *d_a, *d_b, *d_c; 

    //cudaMalloc for d_a, d_b, d_c...

    stat = cublasCreate(&handle); // initialize CUBLAS context

    stat = cublasSetMatrix(m,k, sizeof(*a), a, m, d_a, m);
    stat = cublasSetMatrix(k,n, sizeof(*b), b, k, d_b, k); 

    float al =1.0f;
    float bet =0.0f; 

    stat=cublasSgemm(handle,CUBLAS_OP_T,CUBLAS_OP_T,m,n,k,&al,d_a,m,d_b,k,&bet,d_c,m);

    stat = cublasGetMatrix (m,n, sizeof (*c) ,d_c ,m,c,m); // cp d_c - >c

    if(print == 1) {
    printf ("\nc after Sgemm :\n");
        for(i=0;i<m*n;i++){
                printf ("%f ",c[i]); // print c after Sgemm
        }
    }

    cudaFree (d_a); 
    cudaFree (d_b); 
    cudaFree (d_c);
    cublasDestroy (handle); // destroy CUBLAS context
    free (a); 
    free (b); 
    free (c); 

    return EXIT_SUCCESS ;
}

Результатом является транспонирование умножения A * B, то есть: (A * B) T.

Но я хочу C = A * B в мажорном порядке.

Я надеюсь, что кто-то может мне помочь.

1 Ответ

0 голосов
/ 09 мая 2019

Как вы сказали, cuBLAS интерпретирует матрицы как упорядоченные по основным столбцам, поэтому, когда вы выполняете cublasSgemm(handle,CUBLAS_OP_T,CUBLAS_OP_T,m,n,k,&al,d_a,m,d_b,k,&bet,d_c,m), вы правильно транспонируете каждый вход (который был создан в форме основной строки) при подготовке к интерпретации основных столбцов. Проблема в том, что cuBLAS также выводит результат в порядке столбцов.

Мы введем cuBLAS в вычисления image, которые будут выводиться в главном порядке столбцов и, таким образом, будут выглядеть как image когда мы хитро интерпретируем это в мажорном порядке. Поэтому вместо вычисления AB = C мы делаем image = image. К счастью, image и image мы уже получили самим действием создания A и B в порядок основной строки, поэтому мы можем просто обойти транспонирование с помощью CUBLAS_OP_N. Поэтому измените строку на cublasSgemm(handle,CUBLAS_OP_N,CUBLAS_OP_N,n,m,k,&al,d_b,n,d_a,k,&bet,d_c,n).


Код примера, который вы указали, должен вычислять

image

и после запуска с обновленным вызовом cublasSgemm мы получаем:

c after Sgemm :
548.000000 584.000000 620.000000 656.000000 683.000000 728.000000 773.000000 818.000000 
...