Рассмотрим следующее ядро

__global__ void elementAccess( int *a, int N )
{
  int i = blockDim.x * blockIdx.x + threadIdx.x;
  int z = a[ i ];
}

Который называется

cudaEvent_t start, stop;
float elapsedTime;
cudaEventCreate(&start);
cudaEventRecord(start,0);

elementAccess<<< 1, 1>>>( d_A, 1 );

cudaEventCreate(&stop);
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&elapsedTime, start,stop);

printf("Elapsed time : %f ms\n" ,elapsedTime);

Где d_A — массив целых чисел.

Когда я запускаю код в терминале, я вижу

Elapsed time : 0.015328 ms

Когда я профилирую его с помощью nvprof --metrics SOME_METRICS -o e.nvvp ./element_access, я вижу, что продолжительность ядра составляет 2.95 us.

Итак, почему события часов говорят, что время выполнения ядра составляет 15 мкс, а nvvp говорит, что это 2,95 мкс?

Это две разные вещи? Или чего-то еще не хватает?

3
mahmood 1 Ноя 2019 в 13:32
1
cudaEventCreate может влиять на это. Вы не должны делать это в регионе синхронизации. Создайте все свои мероприятия перед выполнением любой операции cudaEventRecord.
 – 
Robert Crovella
1 Ноя 2019 в 15:13
На самом деле не влияет. Я имею в виду, что cudaEventRecord(start,0); /* kernel */; cudaEventRecord(stop,0); занимает примерно столько же времени. Около 15us.
 – 
mahmood
1 Ноя 2019 в 15:58

1 ответ

Ваше первое измерение (основанное на истекшем времени) включает накладные расходы на запуск ядра. Второй (на основе событий CUDA) в основном исключает накладные расходы на запуск.

Учитывая, что ваше ядро ​​абсолютно ничего не делает (одна загрузка памяти будет оптимизирована из-за отсутствия последующего использования значения), кажется разумным, что истекшее время почти полностью состоит из служебных данных запуска.

2
tera 1 Ноя 2019 в 14:40
Я вижу похожие методы измерения задержки доступа. Например, я хочу измерить задержку памяти. Это означает, что накладные расходы на запуск ядра всегда присутствуют.
 – 
mahmood
1 Ноя 2019 в 14:59