Cuda, чтобы сделать умножение матриц

0

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

__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, потому что память разделяется.

Теги:
parallel-processing
cuda

1 ответ

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

Одна из проблем, которые я вижу в вашем коде, заключается в том, что ваша 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 быстрее, чем CUDA?
  • 0
    CUBLAS использует CUDA, но это высоко оптимизированный код, написанный экспертами. Ваш вопрос аналогичен вопросу, почему MKL быстрее выполняет умножение матриц, чем подпрограмма умножения матриц, которую я написал сам. Ваш матричный код CUDA умножения довольно наивен, и есть базовые оптимизации, которые вы могли бы использовать, чтобы сделать его быстрее. Если вы выполните умножение по матрице Куды в поле поиска в верхнем правом углу этой страницы, вы найдете много примеров различных оптимизаций. Наиболее прямым является использование разделяемой памяти в мозаичном расположении.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню