Почему скорость копирования памяти CUDA ведет себя так, что некоторые постоянные издержки драйвера?

При работе с памятью в CUDA на моем старом GeForce 8800GT всегда возникают странные издержки в 0, 04 мс. Мне нужно передать ~1-2K в постоянную память моего устройства, работать с этими данными на нем и получить только одно значение с плавающей запятой от устройства.

У меня есть типичный код с использованием вычисления GPU:

//allocate all the needed memory: pinned, device global
for(int i = 0; i < 1000; i++)
{
    //Do some heavy cpu logic (~0.005 ms long)        
    cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
    my_kernel<<<128, 128>>>(output);
    //several other calls of different kernels
    cudaMemcpy((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
    // Do some logic with returned value 
}

Я решил измерить скорость работы с памятью GPU этим кодом (прокомментировал все вызовы ядра, добавил cudaDeviceSynchronize вызов):

//allocate all the needed memory: pinned, device global
for(int i = 0; i < 1000; i++)
{
    //Do some heavy cpu logic (~0.001 ms long)        
    cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
    cudaMemcpyAsync((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
    cudaDeviceSynchronize();
    // Do some logic with returned value 
}

Я измерил время выполнения цикла и получил ~0, 05 с (то есть 0, 05 мс за итерацию). Странно то, что когда я пытаюсь сделать больше работы с памятью (добавляя дополнительные вызовы cudaMemcpyToSymbolAsync и cudaMemcpyAsync), я получаю дополнительное время <0, 01 мс на вызов. Это соответствует исследованию этого парня: http://www.cs.virginia.edu/~mwb7w/cuda_support/memory_transfer_overhead.html

Он также получил эти 0, 01 мс за передачу блока 1К на графический процессор. Так откуда взялись эти 0, 04 мс (0, 05 - 0, 01) служебные данные? Есть идеи? Может быть, я должен попробовать этот код на новой карте?

Мне кажется, что после cudaDeviceSynchronize и кода процессора моя GeForce переходит в какой-то режим энергосбережения или что-то в этом роде.

1 ответ

Я рекомендую вам увеличить количество потоков, которые вы реализуете

    //Use malloc() to allocate memory on CPU. 
    //Change mem_size to the total memory to be tranferred to GPU.        
    cudaMemcpyToSymbolAsync(const_dev_mem, pinned_host_mem, mem_size, 0, cudaMemcpyHostToDevice);
    dim3 dimBlock(128,2);
    dim3 dimGrid(64000,1);
    my_kernel<<<dimGrid, dimBlock>>>(output);
    //several other calls of different kernels
    //change size field to 1000*sizeof(FLOAT_T)
    cudaMemcpy((void*)&host_output, output, sizeof(FLOAT_T), cudaMemcpyDeviceToHost);
    // Do some logic with returned value 

Если код дает сбой (из-за большего количества потоков или большего количества памяти GPU), используйте циклы. Но сделай их меньше.

Другие вопросы по тегам