2015-09-21 4 views
-2

Я действительно пытался реализовать функцию в C, чтобы умножить на матрицу строк в cublas. Я не знаю, где я ошибаюсь. В функции ниже A, B и C указаны указатели на матрицу строк правильно. выделено. Я хотел бы сохранить возможность перевода матрицы перед выполнением продукта. Функция ниже не работает.cublassgemm for row-major matrix

void matrixMul(cublasHandle_t handle,float *A,float *B,float *C, int m,int n,int k,int transA,int transB){ 

    cublasStatus_t stat ; // CUBLAS functions status 
    float alfa = 1; 
    float beta = 0; 

    int 
    ma = transA ? n:m, 
    na = transA ? m:n, 


    nb = transB ? k:n, 
    mb = transB ? n:k; 


    if(na!=mb){ 
     puts("Something wrong"); 
    } 

    //(mb,nb)(ma,na) = (mb,na) 
    stat= cublasSgemm_v2(handle, (cublasOperation_t) transB, (cublasOperation_t)transA, 
       nb,ma,mb,&alfa, 
       B,k, 
       A,n,&beta, 
       C,m); 

    switch (stat) { 
     case CUBLAS_STATUS_SUCCESS: 
      puts("Sucess"); 
      break; 
     default: 
      printf(">>>>ERRO %d<<<<\n",stat); 
      break; 
    } 

} 

весь исходный код

// Utilities and system includes 
#include <assert.h> 
#include <helper_string.h> // helper for shared functions common to CUDA Samples 

// CUDA runtime 
#include <cuda_runtime.h> 
#include <cublas_v2.h> 

// CUDA and CUBLAS functions 
#include <helper_functions.h> 

void getFromDevice(float *h_A,float *d_A,int size){ 
    //printf("Copy input data from the host memory to the CUDA device\n"); 
    cudaError_t err = cudaMemcpy(h_A, d_A, size, cudaMemcpyDeviceToHost); 

    if (err != cudaSuccess) 
    { 
     fprintf(stderr, "Failed to copy vector A from host to device (error code %s)!\n", cudaGetErrorString(err)); 
     exit(EXIT_FAILURE); 
    } 
} 
//A = (m,n) 
//B = (n,k) 
//C = (m,k) 
void matrixMul(cublasHandle_t handle,float *A,float *B,float *C, int m,int n,int k,int transA,int transB){ 

    cublasStatus_t stat ; // CUBLAS functions status 
    float alfa = 1; 
    float beta = 0; 

    int 
    ma = transA ? n:m, 
    na = transA ? m:n, 


    nb = transB ? k:n, 
    mb = transB ? n:k; 


    if(na!=mb){ 
     puts("Something wrong"); 
    } 

    //(mb,nb)(ma,na) = (mb,na) 
    stat= cublasSgemm_v2(handle, (cublasOperation_t) transB, (cublasOperation_t)transA, 
       nb,ma,mb,&alfa, 
       B,k, 
       A,n,&beta, 
       C,m); 

    switch (stat) { 
     case CUBLAS_STATUS_SUCCESS: 
      puts("Sucess"); 
      break; 
     default: 
      printf(">>>>ERRO %d<<<<\n",stat); 
      break; 
    } 

} 


float *mallocfDevice(int size){ 
    float *d_C = NULL; 
    cudaError_t err = cudaMalloc((void **)&d_C, size * sizeof(float)); 

    if (err != cudaSuccess) 
    { 
     fprintf(stderr, "Failed to allocate device vector C (error code %s)!\n", cudaGetErrorString(err)); 
     exit(EXIT_FAILURE); 
    }else{ 
     size_t freeM, total; 
     cudaMemGetInfo ( &freeM, &total); 
     printf("MEM:%.3f\n",freeM,total,100 - ((double)freeM/total)*100); 
    } 
    return d_C; 
} 



void printHostMatrix(int nl, int nc, float *h_s){ 
    for(int j = 0; j < nl ; j++) { 
     for(int i = 0; i < (nc) ; i++){ 
      int idx = j*nc + i; 
      printf("%.2f ", h_s[idx]); 
     } 
     printf("\n"); 
    } 

} 


void printfDeviceMatrix(float *d_s,int m, int p){ 
    float *h_s =(float*) malloc(sizeof(float)*m*p); 
    getFromDevice(h_s,d_s,sizeof(float)*m*p); 
    printHostMatrix(m,p,h_s); 
    free(h_s); 
} 


void sendTofDevice(float *h_A,float *d_A,int size){ 
    //printf("Copy input data from the host memory to the CUDA device\n"); 
    cudaError_t err = cudaMemcpy(d_A, h_A, size*sizeof(float), cudaMemcpyHostToDevice); 

    if (err != cudaSuccess) 
    { 
     fprintf(stderr, "Failed to copy vector A from host to device (error code %s)!\n", cudaGetErrorString(err)); 
     exit(EXIT_FAILURE); 
    } 
} 


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

    int ma = 2, 
     na = 3, 
     mb = 3, 
     nb = 2; 

    float A[] = { 1,2,3, 
       4,5,6}; 
    float B[] = {7, 8, 
       9,10, 
       11,12}; 

    float *C = new float[ma*nb]; 



    float *d_a = mallocfDevice(ma*mb), 
      *d_b = mallocfDevice(mb*nb), 
      *d_c = mallocfDevice(ma*nb); 

    sendTofDevice(A,d_a,ma*na); 
    sendTofDevice(B,d_b,mb*nb); 

    cublasHandle_t handle ; // CUBLAS context 
    cublasCreate (&handle); 

    puts("A"); 
    printfDeviceMatrix(d_a,ma,na); 
    puts("B"); 
    printfDeviceMatrix(d_b,mb,nb); 

    matrixMul(handle, d_a,d_b,d_c, 
         ma,na,nb,0,0); 

    puts("AB=C"); 
    printfDeviceMatrix(d_c,ma,nb); 


} 
+0

Не могли бы вы описать свою проблему чуть подробнее? «Не работает» не очень полезно, боюсь – talonmies

+0

Я решил проблему. Я не понял, как использовать cublasgemm для основной матрицы строк. Я проверю ответ. –

+0

Не могли бы вы добавить короткий ответ, объясняющий, как вы решили проблему? (Отвечая на ваши вопросы, все в порядке на [SO]). Это оставит что-то позади для следующего человека, который может найти это через google. – talonmies

ответ

-1

CUBLAS предполагает, что матрица в устройстве хранится в колонке главного:

" , где α и β являются скаляры, а А, В и C - матрицы, хранящиеся в формате столбцов с размерами op (A) m × k, op (B) k × n и C m × n соответственно. Также для матрицы A

Подробнее по адресу: http://docs.nvidia.com/cuda/cublas/index.html#ixzz3mSDJTWrM "

Это означает, что на устройстве необходимо обрабатывать по-разному, чем на хосте.

+0

API CUBLAS (как и любой BLAS), поддерживает работу с матрицами, хранящимися в транспонированном порядке (т. Е. Основной порядок строк), и OP пытается использовать это для выполнения точечного продукта. – talonmies

+1

Возможно использование матриц, которые хранятся в строчном порядке с кубасами, и «матрица должна рассматриваться как по-разному на устройстве, чем на хосте» - это вздор. –

 Смежные вопросы

  • Нет связанных вопросов^_^