2016-03-13 7 views
1

Я пытаюсь заменить мой GPU блок умножения матриц с cublas, но я не получаю то, что я ожидал на тестовом 2х2 случае:cublas умножения матриц, как ожидалось

#include "cuda_runtime.h" 
#include "cublas_v2.h" 
#include "stdio.h" 
#include "omp.h" 


int main(int argc, char **argv) { 

    const int SZ = 2; 
    const size_t MB = SZ*SZ*sizeof(float); 

    cudaSetDevice(0); 

    float *m1, *m2, *m3; 
    float *m1_, *m2_, *m3_; 

    unsigned int i, j; 

    m1 = (float *)malloc(MB); 
    m2 = (float *)malloc(MB); 
    m3 = (float *)malloc(MB); 

    cudaMalloc((float **)&m1_, MB); 
    cudaMalloc((float **)&m2_, MB); 
    cudaMalloc((float **)&m3_, MB); 

    for (i=0; i<SZ*SZ; i++) { 
    j = (int) (i==1); 
    m1[i] = j; 
    j = (int) (i==3); 
    m3[i] = j; 
    printf("m1[%d]=%f m3[%d]=%f\n",i,m1[i],i,m3[i]); 
    } 

    cublasHandle_t handle; 
    cublasCreate(&handle); 

    cublasSetMatrix(SZ,SZ,MB,m1,SZ,m1_,SZ); 
    cublasSetMatrix(SZ,SZ,MB,m3,SZ,m3_,SZ); 

    float al = 1.0f; 
    float bt = 0.0f; 

    cublasSgemm(handle,CUBLAS_OP_N,CUBLAS_OP_N,SZ,SZ,SZ,&al,m3_,SZ,m1_,SZ,&bt,m2_,SZ); 
    printf("\n%s\n\n", cudaGetErrorString(cudaDeviceSynchronize())); 
    cublasGetMatrix(SZ,SZ,MB,m2_,SZ,m2,SZ); 

    for (i=0; i<SZ*SZ; i++) 
    printf("m2[%d]=%f\n",i,m2[i]); 

    free(m1); 
    free(m2); 
    free(m3); 

    cublasDestroy(handle); 

    cudaFree(m1_); 
    cudaFree(m2_); 
    cudaFree(m3_); 


    cudaDeviceReset(); 

    return 0; 
} 

Так что я ожидал для m2 вернуть следующая матрица:

[0 1 
0 0] 

в результате умножения

[0 1 
0 0] 

и

[0 0 
0 1] 

Я используем обращенный заказ на m1 и m3 так, что должно дать мне правильный выход для m2, извлекаемые при условии, что cublas {Set/Get} Матрица работает в столбцах. Но вот вывод кода:

m1[0]=0.000000 m3[0]=0.000000 
m1[1]=1.000000 m3[1]=0.000000 
m1[2]=0.000000 m3[2]=0.000000 
m1[3]=0.000000 m3[3]=1.000000 

no error 

m2[0]=0.000000 
m2[1]=0.000000 
m2[2]=0.000000 
m2[3]=0.000000 

Я не знаю, что я здесь делаю неправильно; Я был бы очень признателен за ваш вклад.

+0

Параметр '#include "omp.h"' линия, конечно, здесь неуместна. – oligilo

ответ

1

Прототип cublasGetMatrix является:

cublasStatus_t cublasGetMatrix(int rows, int cols, int elemSize, 
         const void *A, int lda, void *B, int ldb); 

elemSize должен быть размер одного элемента матрицы (т.е. sizeof(float)). Это то же самое для cublasSetMatrix:

cublasStatus_t cublasSetMatrix(int rows, int cols, int elemSize, 
         const void *A, int lda, void *B, int ldb) 
+0

Ах, большое вам спасибо! Вы случайно знаете, могу ли я заменить 'cublasGetMatrix' на' cudaMemcpy', чтобы избежать переполнения столбца и выполнить умножение матрицы в обычном порядке (для ввода строки)? – oligilo

+2

Конечно, вы можете. Но следует либо сохранить вашу матрицу с содержимым в столбце майор ... или использовать cublasSgemm с параметрами транспонирования, если вы уверены, что трансформированные матрицы будут такими же, как и в основной версии столбца. Также я бы рекомендовал использовать cudaMemcpy2D, чтобы получить хорошее выравнивание (возможно, вам придется отрегулировать параметры LDx при вызове Sgemm) – jyvet

+0

А, я вижу; Я думал, что копирование с помощью 'cudaMemcpy' будет автоматически копировать матрицу в правильном порядке для' cublas', чтобы использовать независимо от того, представляет ли она входной сигнал строки или столбца. Я вижу, где я ошибся в своих мыслях; еще раз спасибо! – oligilo