2016-10-06 10 views
0

Я хочу узнать, как количество потоков в блоке влияет на производительность и скорость программы cuda. Я написал простой код векторного сложения, вот мой код:Эксперимент, чтобы узнать влияние размера блока на скорость программы cuda

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } 
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true) 
{ 
    if (code != cudaSuccess) 
    { 
     fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); 
     if (abort) exit(code); 
    } 
} 
__global__ void gpuVecAdd(float *a, float *b, float *c, int n) { 
    int id = blockIdx.x * blockDim.x + threadIdx.x; 
    if (id < n) { 
     c[id] = a[id] + b[id]; 
    } 
} 
int main() { 
    int n = 1000000; 
    float *h_a, *h_b, *h_c, *t; 
    srand(time(NULL)); 
    size_t bytes = n* sizeof(float); 
    h_a = (float*) malloc(bytes); 
    h_b = (float*) malloc(bytes); 
    h_c = (float*) malloc(bytes); 
    for (int i=0; i<n; i++) 
     { 
     h_a[i] =rand()%10; 
      h_b[i] =rand()%10; 
     } 
    float *d_a, *d_b, *d_c; 
    cudaMalloc(&d_a, bytes); 
    cudaMalloc(&d_b, bytes); 
    cudaMalloc(&d_c, bytes); 

    gpuErrchk(cudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice)); 
    gpuErrchk(cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice)); 

    clock_t t1,t2; 
    t1 = clock(); 
    int block_size = 1024; 
    gpuVecAdd<<<ceil(float(n/block_size)),block_size>>>(d_a, d_b, d_c, n); 
    gpuErrchk(cudaPeekAtLastError()); 
    t2 = clock(); 
    cout<<(float)(t2-t1)/CLOCKS_PER_SEC<<" seconds"; 
    gpuErrchk(cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost)); 
cudaFree(d_a); 
    cudaFree(d_b); 
    cudaFree(d_c); 
    free(h_a); 
    free(h_b); 
    free(h_c); 
} 

Я прочитал this post и на основе ответить на talonmies "Количество потоков на блок должен быть круглым кратен размеру основы, которая 32 на все текущее оборудование «

Я проверил код с различным количеством потоков на блок, например, 2 и 1024 (что умножается на 32, а также максимальное количество потоков на блок). Среднее время работы для обоих размеров почти одинаковое, и я не вижу огромной разницы между ними. Почему это? Является ли мой бенчмаркинг неправильным?

+1

Вы только накладные расходы на запуск. На самом деле вы не определяете продолжительность ядра. После вызова 'cudaPeekAtLastError' добавьте вызов' cudaDeviceSynchronize() ', который заставит всю продолжительность ядра отображаться в вашем времени. –

+0

@RobertCrovella Да! это была проблема. Пожалуйста, напишите свой ответ, чтобы я мог отметить его как правильный ответ. – starrr

ответ

1

Запуск ядра GPU в CUDA: асинхронный. Это означает, что управление будет возвращено в поток ЦП до того, как ядро ​​закончит выполнение.

Если мы хотим, чтобы поток ЦП запустил время ядра, мы должны заставить процессорный поток ждать завершения ядра. Мы можем это сделать, поместив вызов в cudaDeviceSynchronize() в область синхронизации. Затем измеренное время будет включать полную продолжительность выполнения ядра.