CUDA: cudaEvent_t и cudaThreadSynchronize использование

#timer #cuda

#таймер #cuda

Вопрос:

Я немного смущен использованием cudaEvent_t . В настоящее время я использую clock() вызов, подобный этому, чтобы определить продолжительность вызова ядра:

 cudaThreadSynchronize();
clock_t begin = clock();

fooKernel<<< x, y >>>( z, w );

cudaThreadSynchronize();
clock_t end = clock();

// Print time difference: ( end - begin )
  

Я рассматриваю возможность использования таймера с более высоким разрешением cudaEvent_t . Нужно ли мне вызывать, cudaThreadSynchronize() прежде чем я запишу время использования cudaEventRecord() , или это излишне?

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

Ответ №1:

На самом деле существует еще больше функций синхронизации ( cudaStreamSynchronize ). В руководстве по программированию есть подробное описание того, что делает каждый из них. Использование событий в качестве таймеров в основном сводится к этому:

 //create events
cudaEvent_t event1, event2;
cudaEventCreate(amp;event1);
cudaEventCreate(amp;event2);

//record events around kernel launch
cudaEventRecord(event1, 0); //where 0 is the default stream
kernel<<<grid,block>>>(...); //also using the default stream
cudaEventRecord(event2, 0);

//synchronize
cudaEventSynchronize(event1); //optional
cudaEventSynchronize(event2); //wait for the event to be executed!

//calculate time
float dt_ms;
cudaEventElapsedTime(amp;dt_ms, event1, event2);
  

Важно синхронизировать event2 , потому что вы хотите убедиться, что все было выполнено, прежде чем вычислять время. Поскольку оба события и ядро находятся в одном потоке (порядок сохранен), event1 и kernel также были выполнены.

Вы могли бы вызвать вместо этого cudaStreamSynchronize or даже cudaThreadSynchronize , но в этом случае оба варианта являются излишними.

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

1. LumpN: Почему событие не записывается при вызове cudaEventRecord? Если он не записан при этом вызове, как он представляет время, затраченное этим ядром?

2. @Ashwin: Событие записывается, когда оно достигает вершины потока, который действует как FIFO. Когда вы вызываете cudaEventRecord, вы запускаете событие в поток. Если в потоке перед событием есть работа, событие остается необработанным в потоковом FIFO до завершения каждой операции, предшествующей ему. Все эти вызовы являются асинхронными по отношению к вызывающему потоку хоста.