2015-07-07 2 views
0

Мне нужно измерить разницу во времени между распределением нормальной памяти процессора с помощью new и вызовом cudaMallocManaged. Мы работаем с единой памятью и пытаемся выяснить компромиссы с переключением на cudaMallocManaged. (Ядра, кажется, работают намного медленнее, вероятно, из-за нехватки кеширования или чего-то еще.)Измерение CUDA Время выделения

В любом случае, я не уверен, что лучший способ времени для этих распределений. Будет ли один из process_real_cpu_clock, process_user_cpu_clock, или process_system_cpu_clock, дать мне лучшие результаты? Или я должен использовать обычный системный вызов времени в C++ 11? Или я должен использовать материал cudaEvent для синхронизации?

Я полагаю, что я не должен использовать события cuda, потому что они предназначены для хронометрирования процессов графического процессора и не будут иметь решающего значения для вызовов времени cpu (исправьте меня, если я ошибаюсь там.) Если бы я мог использовать cudaEvents только mallocManaged один, что было бы наиболее точным, чтобы сравнить с тем, когда вызов new? Я просто не знаю достаточно о распределении памяти и времени. Все, что я читаю, похоже, просто заставляет меня запутываться из-за дрянной документации от boost и nvidia.

ответ

1

Я рекомендую:

auto t0 = std::chrono::high_resolution_clock::now(); 
// what you want to measure 
auto t1 = std::chrono::high_resolution_clock::now(); 
std::cout << std::chrono::duration<double>(t1-t0).count() << "s\n"; 

Этот выход разницу в секундах, представленных в виде double.

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

Некоторые реализации std::chrono::high_resolution_clock были менее впечатляющими, но со временем улучшаются. Вы можете оценить свою реализацию с помощью:

auto t0 = std::chrono::high_resolution_clock::now(); 
auto t1 = std::chrono::high_resolution_clock::now(); 
std::cout << std::chrono::duration<double>(t1-t0).count() << "s\n"; 

То есть, насколько быстро ваша реализация может получить текущее время? Если он медленный, два последовательных вызова будут демонстрировать большое время между ними. В моей системе (в -O3) это выводит на порядок:

1.2e-07s 

, что означает, что я могу раз что-то, что занимает порядка 1 мкс. Чтобы получить более точное измерение, чем это, мне нужно перебрать многие операции и разделить на количество операций, вычитая издержки на цикл, если это будет значительным.

Если ваша реализация std::chrono::high_resolution_clock окажется неудовлетворительной, возможно, вы сможете построить свои собственные часы chronoalong the lines of this. Недостатком, очевидно, является немного не портативная работа. Однако вы получаете бесплатную инфраструктуру std::chronoduration и time_point (преобразование времени и единиц измерения).

+0

Я, кажется, обходящий 9e-7 секунд. Завершение звонка будет, вероятно, приближать меня к тому, что я хочу. Я просто не уверен, что синхронизация выделения cuda таким образом уловит какие-то накладные расходы на синхронизацию, которые на самом деле не должны быть синхронизированы. – Cory

3

Вы можете использовать события CUDA для измерения времени выполнения функций на хосте .

cudaEventElapsedTime вычисляет прошедшее время между двумя событиями (в миллисекундах с разрешением около 0,5 микросекунды).

Узнайте больше на сайте: http://docs.nvidia.com/cuda/cuda-runtime-api/index.html

Кроме того, если вы также заинтересованы в синхронизации вашего ядра времени выполнения, вы увидите, что событие API CUDA автоматически блокирует выполнение кода и ждет, пока какой-либо асинхронный (например, вызов ядра).

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

Профайлер `nvprof ', поставляемый с инструментарием CUDA, может помочь понять и оптимизировать производительность вашего приложения CUDA.

Узнайте больше на сайте: http://docs.nvidia.com/cuda/profiler-users-guide/index.html

+0

Я не был уверен, что работа таймера cudaEvent работает правильно, потому что он сообщал, что использование 'new', чтобы мой массив занимал 80 раз дольше, чем использование' cuMallocManaged', что кажется неправильным. (P.S. Спасибо за указание профайлера. Похоже, это будет очень полезно для выбора времени после выделения.) – Cory

+0

Вы должны добавить минимальный пример, демонстрирующий это поведение. Это может помочь получить лучший ответ. – pQB

+0

Если в потоке по умолчанию уже выполняется (асинхронное) ядро, и я добавляю cudaEventRecord в FIFO потока по умолчанию, cudaEvent будет блокироваться до тех пор, пока ядро ​​не завершит работу до «регистрации», верно? Другими словами, он не фиксирует время выполнения ЦП, которое имело место, пока работало ядро, правильно? – nirvanaswap

Смежные вопросы