Was ist der Unterschied zwischen der Verwendung eines CPU-Timers und des CUDA-Timer-Ereignisses , um die Zeit zu messen, die für die Ausführung eines CUDA-Codes benötigt wird? Welche sollte ein CUDA-Programmierer verwenden und warum?
Die Verwendung von CPU-Zeitgebern würde das Aufrufen von cudaThreadSynchronize
erfordern, bevor irgendeine Zeit bemerkt wird. Zum Feststellen der Zeit kann clock()
verwendet werden oder ein hochauflösender Leistungszähler wie QueryPerformanceCounter
(unter Windows) könnte abgefragt werden.
CUDA-Timer-Ereignis würde die Aufnahme vor und nach der Verwendung von cudaEventRecord
beinhalten. Zu einem späteren Zeitpunkt würde die verstrichene Zeit durch Aufrufen von cudaEventSynchronize
für die Ereignisse erhalten, gefolgt von cudaEventElapsedTime
, um die verstrichene Zeit zu erhalten.
Die Antwort auf den ersten Teil der Frage lautet, dass cudaEvents-Timer auf hochauflösenden Zählern an Bord der GPU basieren, und sie haben eine niedrigere Latenz und bessere Auflösung als ein Host-Timer, weil sie "aus dem Metall" kommen. Sie sollten eine Sub-Mikrosekunden-Auflösung von den cudaEvents-Timern erwarten. Sie sollten sie aus genau diesem Grund für das Timing von GPU-Operationen bevorzugen. Die pro-stream-Eigenschaft von cudaEvents kann auch nützlich sein, um asynchrone Operationen wie simultane Kernel-Ausführung und überlappende Kopie und Kernel-Ausführung zu instrumentieren. Eine solche Zeitmessung ist mit Host-Timern praktisch unmöglich.
BEARBEITEN: Ich werde den letzten Absatz nicht beantworten, weil Sie ihn gelöscht haben.
Der Hauptvorteil der Verwendung von CUDA-Ereignissen für das Timing besteht darin, dass sie weniger Störungen aufgrund anderer Systemereignisse wie Paging oder Interrupts von der Festplatte oder dem Netzwerkcontroller ausgesetzt sind. Da der Ereignisrecord cu (da) asynchron ist, gibt es auch weniger einen Heisenberg-Effekt, wenn kurze, GPU-intensive Operationen durchgeführt werden.
Ein weiterer Vorteil von CUDA-Ereignissen besteht darin, dass sie über eine saubere plattformübergreifende API verfügen, ohne gettimeofday () oder QueryPerformanceCounter () umbrechen zu müssen.
Eine letzte Anmerkung: Seien Sie vorsichtig, wenn Sie gestreamte CUDA-Ereignisse für das Timing verwenden. Wenn Sie den NULL-Stream nicht angeben, können Sie Timing-Vorgänge beenden, die Sie nicht beabsichtigen. Es gibt eine gute Analogie zwischen CUDA-Ereignissen und dem Lesen des Zeitstempelzählers der CPU, bei dem es sich um einen Serialisierungsbefehl handelt. Auf modernen superskalaren Prozessoren macht die Serialisierungssemantik das Timing eindeutig. Wie bei RDTSC sollten Sie die Ereignisse, die Sie zeitlich bestimmen möchten, immer mit genügend Arbeit versehen, damit das Timing sinnvoll ist (genauso wie Sie RDTSC nicht sinnvoll einsetzen können, um einen einzelnen Maschinenbefehl sinnvoll zu programmieren).