Ядро синхронизации запускается в CUDA при использовании Thrust

#c #time #cuda #thrust

#c #время #cuda #thrust

Вопрос:

Запуск ядра в CUDA обычно происходит асинхронно, что (насколько я понимаю) означает, что после запуска ядра CUDA управление немедленно возвращается к центральному процессору. Центральный процессор продолжает выполнять некоторую полезную работу, пока графический процессор занят обработкой чисел, если только центральный процессор не будет принудительно остановлен с помощью cudaThreadsynchronize() или cudaMemcpy() .

Сейчас я только начал использовать библиотеку Thrust для CUDA. Являются ли вызовы функций в Thrust синхронными или асинхронными?

Другими словами, если я вызываю thrust::sort(D.begin(),D.end()); где D — вектор устройства, имеет ли смысл измерять время сортировки с помощью

         start = clock();//Start

             thrust::sort(D.begin(),D.end());

        diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
        std::cout << "nDevice Time taken is: " <<diff<<std::endl;
  

Если вызов функции асинхронный, то разница будет равна 0 секундам для любого вектора (что нежелательно для таймингов), но если оно синхронное, я действительно получу производительность в реальном времени.

Комментарии:

1. Я скептически отношусь к использованию clock для синхронизации thrust из-за его паршивого разрешения. В прошлом у меня это плохо работало. Вместо этого вам следует использовать CUDA event API.

Ответ №1:

Вызовы Thrust, которые вызывают ядра, являются асинхронными, точно так же, как и базовые API CUDA, которые использует thrust. Вызовы Thrust, которые копируют данные, синхронны, точно так же, как и базовые API CUDA, которые использует thrust.

Таким образом, в вашем примере будут измеряться только накладные расходы на запуск ядра и настройку на стороне хоста thrust, а не сама операция. Что касается синхронизации, вы можете обойти это, вызвав либо cudaThreadSynchronize , либо cudaDeviceSynchronize (более поздний вариант в CUDA 4.0 или более поздней версии) после запуска ядра thrust. В качестве альтернативы, если вы включаете операцию копирования после запуска ядра и записываете время остановки после этого, ваше время будет включать настройку, выполнение и копирование.

В вашем примере это будет выглядеть примерно так

    start = clock();//Start 

   thrust::sort(D.begin(),D.end()); 
   cudaThreadSynchronize(); // block until kernel is finished

   diff = ( clock() - start ) / (double)CLOCKS_PER_SEC; 
   std::cout << "nDevice Time taken is: " <<diff<<std::endl; 
  

Комментарии:

1. Это не совсем верно, большинство из них асинхронны, но некоторые нет. groups.google.com/group/thrust-users/browse_thread/thread/… Кроме того, thrust-вызовы, которые возвращают значение, например reduction, являются блокирующими groups.google.com/group/thrust-users/msg/cd7542285070f893 И cudaHostSynchronize должно быть cudaDeviceSynchronize.

2. разве вам не нужно использовать события для вычисления времени выполнения устройства?