Проблема с временем отклика в CUDA, почему процессор быстрее, чем GPU? - PullRequest
1 голос
/ 31 марта 2020

Привет, у меня проблема с откликом по времени. Я получаю больше времени отклика на GPU, чем на CPU. Используемый алгоритм представляет собой алгоритм умножения матриц

с использованием следующих функций:

// Start timers
cudaEvent_t timer1, timer2;
cudaEventCreate(&timer1);
cudaEventCreate(&timer2);
cudaEventRecord(timer1, 0);
cudaEventSynchronize(timer1);

// Stop timers
    cudaEventRecord(timer2, 0);
    cudaEventSynchronize(timer1);
    cudaEventSynchronize(timer2);
    float elapsed;
    cudaEventElapsedTime(&elapsed, timer1, timer2);

    cudaDeviceReset();
    return elapsed;

вот мой код на GPU:

float Mult_gpu(float* hostPtr, float* hostPtr2, float* hostPtr3, int size, int Ncols, int Nrows, int n) {
size_t pitch;

check("Creating timers");
cudaEvent_t timer1, timer2;
cudaEventCreate(&timer1);
cudaEventCreate(&timer2);
cudaEventRecord(timer1, 0);
cudaEventSynchronize(timer1);

/******************************************/
/***Configuracion de las matrices en gpu***/
/******************************************/
float* devPtr;
cudaMallocPitch(&devPtr, &pitch, n * sizeof(float), Nrows);
cudaMemcpy2D(devPtr, pitch, hostPtr, n * sizeof(float), n * sizeof(float), Nrows, cudaMemcpyHostToDevice);

float* devPtr2;
cudaMallocPitch(&devPtr2, &pitch, Ncols * sizeof(float), n);
cudaMemcpy2D(devPtr2, pitch, hostPtr2, Ncols * sizeof(float), Ncols * sizeof(float), n, cudaMemcpyHostToDevice);

float* devPtr3;
cudaMallocPitch(&devPtr3, &pitch, Ncols * sizeof(float), Nrows);

//dim3 gridSize(iDivUp(Ncols3, BLOCKSIZE_x), iDivUp(Nrows3, BLOCKSIZE_y));
//dim3 blockSize(BLOCKSIZE_y, BLOCKSIZE_x);
dim3 block(32, 32);                                                     //hilos por bloque
dim3 grid((size / block.x) + 1, (size / block.y) + 1);                  //numero de bloques

/**************************/
/**Lanzamiento del kernel**/
/**************************/

Mult << <grid, block >> > (devPtr, devPtr2, devPtr3, pitch, Ncols, Nrows, n);
cudaDeviceSynchronize();

/*********************************/
/***Copiado de devPtr a hosPtr2***/
/*********************************/
cudaMemcpy2D(hostPtr3, Ncols * sizeof(float), devPtr3, pitch, Ncols * sizeof(float), Nrows, cudaMemcpyDeviceToHost);
//cudaMemcpy(hostPtr3, devPtr3, size * sizeof(float), cudaMemcpyDeviceToHost);

cudaFree(devPtr);
cudaFree(devPtr2);
cudaFree(devPtr3);
// Stop timers
cudaEventRecord(timer2, 0);
cudaEventSynchronize(timer1);
cudaEventSynchronize(timer2);
float elapsed;
cudaEventElapsedTime(&elapsed, timer1, timer2);

cudaDeviceReset();
return elapsed;

}

, а вот мой код на CPU

   float Mult_cpu(float* hostPtrA, float* HostPtrB, float* hostPtrC, int Ncols, int Nrows, int n)
{
    cudaEvent_t timer1, timer2;
    cudaEventCreate(&timer1);
    cudaEventCreate(&timer2);
    cudaEventRecord(timer1, 0);
    cudaEventSynchronize(timer1);

    for (int i = 0; i < Nrows; ++i) {
        for (int j = 0; j < Ncols; ++j) {
            float suma = 0;
            for (int k = 0; k < n; ++k) {
                suma += hostPtrA[i * n + k] * HostPtrB[k * Ncols + j];
            }
            hostPtrC[i * Ncols + j] = suma;

        }
    }

    // Stop timers
    cudaEventRecord(timer2, 0);
    cudaEventSynchronize(timer1);
    cudaEventSynchronize(timer2);
    float elapsed;
    cudaEventElapsedTime(&elapsed, timer1, timer2);

        return elapsed;
    }

, когда я использую матрицу 500x500 или любую матрицу Процессор работает быстрее, чем графический процессор, и я не понимаю, почему я не знаю, в чем проблема - в моей программе ядра или функциях CUDA, которые используют

мой код ядра

__global__ void Mult(float* devPtrA, float* devPtrB, float* devPtrC, size_t pitch, int Ncols, int Nrows, int n)
{
    float temp;

    int r = blockDim.y * blockIdx.y + threadIdx.y;      //for (int f = 0; f <= fil - 1; f += 1) equivalencia en for
    int c = blockDim.x * blockIdx.x + threadIdx.x;      //for (int c = 0; c <= col - 1; c += 1)
    if ((r < Ncols) && (c < Nrows)) {
        for (int c2 = 0; c2 < n; c2++) {
            float* vertical = (float*)((char*)devPtrA + r * pitch);
            float element1 = vertical[c2];
            float* horizontal = (float*)((char*)devPtrB + c2 * pitch);
            float element2 = horizontal[c];
            temp += element1 * element2;
        }


        //printf("\nla fila es: %d la columna es: %d el valor es: %8.4f\n\n", r, c, temp);
        float* vertical2 = (float*)((char*)devPtrC + r * pitch);
        vertical2[c] = temp;
    }
}

Ответы [ 2 ]

0 голосов
/ 05 апреля 2020

CudaMallo c действительно медленно. Если вы заранее знаете размер ваших матриц, выполните инициализацию в начале вашей программы.

0 голосов
/ 03 апреля 2020

Вам следует ознакомиться с концепцией архитектуры SIMT, моделью исполнения CUDA и расхождением ветвей . Проанализируйте производительность ядра CUDA с помощью profiler . Я подозреваю, что условие if ((r < Ncols) && (c < Nrows)) в вашем ядре вызывает расхождение потоков в каждой деформации и, следовательно, снижение производительности. Также pitch влияет на глобальную модель доступа к памяти в вашем коде, что является еще одним фактором производительности ядер CUDA. Некоторые другие отличные советы по оптимизации можно найти здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...