2014-02-21 4 views
0

есть проблема создания Матричного умножения с использованием cuda. Я должен сделать A * A * A * A и сохранить его в hB. С Cublas все в порядке, но я не могу сделать это с CUDA. Размер может быть высокое значение, как 2000. Это мой код:Cuda, чтобы сделать Матричное умножение

__global__ void CudaMM(float *A, float *B, int N) 
{ 

    int row = blockIdx.y*blockDim.y + threadIdx.y; 
    int col = blockIdx.x*blockDim.x + threadIdx.x; 

    float sum = 0.f; 
    for (int n = 0; n < N; ++n) 
     sum += A[row*N+n]*A[n*N+col]; 

    B[row*N+col] = sum; 
} 

void CudaMult(int dimension,float *hMatrice,float *hB,float *d_A,float *d_B){ 
    int N,K; 
    K = 100;    
    N = K*BLOCK_SIZE; 

    dim3 threadBlock(BLOCK_SIZE,BLOCK_SIZE); 
    dim3 grid(K,K); 

    cudaMemcpy(d_A,hMatrice,dimension*dimension*sizeof(float),cudaMemcpyHostToDevice); 

CudaMM<<<grid,threadBlock>>>(d_A,d_B,N); 

cudaMemcpy(hB,d_B,dimension*dimension*sizeof(float),cudaMemcpyDeviceToHost); 


} 

void CublasFindConnect(int dimension,float* mat,float* B){ 


    float *d_A,*d_B; 
    cudaMalloc(&d_A,dimension*dimension*sizeof(float)); 
    cudaMalloc(&d_B,dimension*dimension*sizeof(float)); 

    int w=0; 
    while(w<5){ 

     CudaMult(dimension,mat,B,d_A,d_B); 

      // Copy Matrix computed B to previous M 

      for (m=0; m<dimension; m++) { 

       for (n=0; n<dimension; n++) { 
        mat[m*dimension+n]=B[m*dimension+n]; 
        B[m*dimension+n]=0; 
       } 
      } 

    w++; 
    } 

cudaFree(d_A); 
cudaFree(d_B); 

} 

Я установил последний CUDA 6, что он не требует cudaMemCpy, потому что память разделяется.

+0

Вы выполняете [правильную проверку ошибок для своей программы CUDA] (http://stackoverflow.com/q/14038589/2386951)? – Farzad

ответ

1
  • Предлагаю вам начать с правильного cuda error checking по коду, который вы указали, и посмотреть, какие результаты вы получите.
  • Будет лучше, если вы также укажете код. Например, что такое BLOCK_SIZE? Идея не в том, чтобы рассказать мне, что такое BLOCK_SIZE, но чтобы показать код.
  • В отличие от функции, на которую вы ссылаетесь в CUDA 6, есть особые требования (например, использование cudaMallocManaged()), которые вы не встречаете, но тем не менее ваш код не зависит от единой памяти, поэтому это не имеет значения.

Одна из проблем, я могу видеть в своем коде, что ваша dimension переменная является произвольным (вы сказать, что это может быть до большого числа, как 2000), но ваш размер вычислений фиксируется на N=K*BLOCK_SIZE;. Предположительно, если ваш BLOCK_SIZE имеет некоторое значение, например 16 или 32, то он будет соответствовать вашему приблизительному максимальному размеру dimension ~ 2000.

Проблема возникает из-за того, что размер вашей сетки потенциально превышает допустимый размер массива. Вы запускаете сетку N x N, но N может быть больше dimension. Это означает, что некоторые из запущенных потоков могут попытаться получить доступ к матрицам (A и B) за пределами их допустимых размеров.

Вы можете исправить это с помощью «проверки потока» в ядре, что-то вроде этого:

__global__ void CudaMM(float *A, float *B, int N) 
{ 

    int row = blockIdx.y*blockDim.y + threadIdx.y; 
    int col = blockIdx.x*blockDim.x + threadIdx.x; 

    if ((row < N) && (col < N)) { 

     float sum = 0.f; 
     for (int n = 0; n < N; ++n) 
     sum += A[row*N+n]*A[n*N+col]; 

     B[row*N+col] = sum; 
    } 
} 

и вам нужно будет модифицировать ядро ​​розарий:

CudaMM<<<grid,threadBlock>>>(d_A,d_B,dimension); 

Вы могли бы также хотите рассмотреть выбор размеров сетки на основе вашего фактического dimension, вместо того, чтобы фиксироваться на 100*BLOCK_SIZE, но это не обязательно для того, чтобы код работал.

+0

Спасибо. У меня есть вопрос. Почему Cublas Multiplication быстрее, чем CUDA? – user3331951

+0

CUBLAS использует CUDA, но это высоко оптимизированный код, написанный экспертами. Ваш вопрос аналогичен вопросу о том, почему MKL быстрее при умножении матрицы умножается на матричную процедуру умножения, которую я написал сам. Ваша матрица умножает код CUDA довольно наивна, и есть основные оптимизации, которые вы могли бы использовать, чтобы ускорить ее работу. Если вы ищете матрицу cuda, умножьте ее в поле поиска в правом верхнем углу этой страницы, вы найдете множество примеров различных оптимизаций. Самый прямой - использовать разделяемую память в черепичной компоновке. –

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