CUDA профилированные достигнуты занимают очень низко;как поставить диагноз? - PullRequest
3 голосов
/ 23 февраля 2012

Когда я запускаю профилировщик для моего кода, часть вывода выглядит так:

Limiting Factor
Achieved Occupancy:  0.02 ( Theoretical Occupancy:  0.67 )
IPC:  1.00 ( Maximum IPC:  4 )

Достигнутая занятость 0,02 кажется ужасно низкой.Возможно ли, что это связано с отсутствием CSV-файлов в профиле?Он жалуется на:

Program run #18 completed.
Read profiler output file for context #0, run #1, Number of rows=6
Error : Error in profiler data file '/.../temp_compute_profiler_1_0.csv' at line number 1. No column found
Error in reading profiler output:
Application : "/.../bin/python".
Profiler data file '/.../temp_compute_profiler_2_0.csv' for application run 2 not found.
Read profiler output file for context #0, run #4, Number of rows=6

Мои блоки - 32 * 4 * 1, сетка - 25 * 100, и тестирование показало, что 32 регистра обеспечивают лучшую производительность (даже если это приводит к разливу).

Если число 0,02 верно, как я могу отладить, что происходит?Я уже пытался переместить вероятных кандидатов в общую и / или постоянную память, экспериментировать с launch_bounds , перемещать данные в текстуры и т. Д.

Редактировать: если будет больше данных из профиля, будетполезно, просто дайте мне знать, и я могу предоставить это.Спасибо за прочтение.

Редактировать 2: запрошенные данные.

IPC: 1.00
Maximum IPC: 4
Divergent branches(%): 6.44
Control flow divergence(%): 96.88
Replayed Instructions(%): -0.00
Global memory replay(%): 10.27
Local memory replays(%): 5.45
Shared bank conflict replay(%): 0.00
Shared memory bank conflict per shared memory instruction(%): 0.00

L1 cache read throughput(GB/s): 197.17
L1 cache global hit ratio (%): 51.23
Texture cache memory throughput(GB/s): 0.00
Texture cache hit rate(%): 0.00
L2 cache texture memory read throughput(GB/s): 0.00
L2 cache global memory read throughput(GB/s): 9.80
L2 cache global memory write throughput(GB/s): 6.80
L2 cache global memory throughput(GB/s): 16.60
Local memory bus traffic(%): 206.07
Peak global memory throughput(GB/s): 128.26

The following derived statistic(s) cannot be computed as required counters are not available: 
Kernel requested global memory read throughput(GB/s) 
Kernel requested global memory write throughput(GB/s) 
Global memory excess load(%) 
Global memory excess store(%) 
Achieved global memory read throughput(GB/s) 
Achieved global memory write throughput(GB/s) 

Решение (я):

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

Достигнутая 0,02 занятость была вызвана active_warps и active_cycles (и, возможно, другие значения), достигнув максимума (2 ** 32-1).Уменьшение размера входных данных в профилированном сценарии привело к появлению гораздо большего количества правильных значений (включая более качественную / более реалистичную статистику IPC и ветвления).

Ответы [ 3 ]

4 голосов
/ 24 февраля 2012

Аппаратные счетчики, используемые Visual Profiler, Parallel Nsight и профилировщиком командной строки CUDA, являются 32-разрядными счетчиками и будут переполнены в течение 2 ^ 32 / секунд шейдера (~ 5 с). Некоторые счетчики переполняются быстрее, чем это. Если вы видите значения MAX_INT или если ваша продолжительность в секундах, вы, скорее всего, увидите неправильные результаты в инструментах.

Я рекомендую разделить запуск вашего ядра на 2 или более запусков для профилирования, чтобы продолжительность запуска составляла менее 1-2 секунд. В вашем случае теоретическая занятость составляет 67% (32 деформации / SM) и размер блока 4 деформации. При разделении работы вы хотите убедиться, что каждый SM полностью загружен и предпочтительно получает несколько волн блоков. Для каждого запуска попробуйте запустить NumSMs * MaxBlocksPerSM * 10 Blocks. Например, если у вас GTX560 с 8 SM и указанная выше конфигурация, вы бы разбили один запуск из 2500 блоков на 4 запуска по 640, 640, 640 и 580.

Улучшенная поддержка обработки переполнений должна быть в следующей версии инструментов.

3 голосов
/ 23 февраля 2012

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

Достигнутая занятость является мерой (active_warps / active_cyles) / max_warps_per_sm.

Достигнутая занятость 0,02 означает, что на SM активен только 1 деформация. При запуске 10000 деформаций (2500 блоков * 128 потоков / WARP_SIZE) это может произойти только в том случае, если у вас чрезвычайно расходящийся код, при котором все деформации, кроме 1, сразу выходят и 1 деформация выполняется в течение очень длительного времени. Также весьма маловероятно, что вы могли бы достичь IPC 1 с этим достигнутым заполнением, поэтому я подозреваю ошибку в сообщаемом значении.

Если вам нужна помощь в диагностике проблемы, я бы предложил вам

  1. опубликовать информацию об устройстве
  2. убедитесь, что вы запустили <<<{25,100,1}, {128, 4, 1}>>>
  3. оставьте свой код

Если вы не можете опубликовать свой код, я бы порекомендовал захватить счетчики active_cycles и active_warps и рассчитать достигнутую занятость как

(active_warps / active_cycles) / 48

Учитывая, что в вашем журнале профилировщика есть ошибки, возможно, результаты неверны.

Я думаю, что из вывода вы используете более старую версию Visual Profiler. Вы можете рассмотреть возможность обновления до версии 4.1, которая улучшит как сборку счетчиков PM, так и поможет дать подсказки о том, как улучшить ваш код.

0 голосов
/ 23 февраля 2012

Кажется, что (большая часть) ваша проблема здесь такова:

Control flow divergence(%): 96.88

Похоже, что в 96,88% случаев потоки не выполняют одну и ту же инструкцию вв то же время.Графический процессор может действительно запускать потоки параллельно, когда каждый поток в деформации выполняет одну и ту же инструкцию в одно и то же время.Такие вещи, как операторы if-else, могут привести к тому, что некоторые потоки данной деформации войдут в if, а некоторые потоки - в else, что приведет к расхождению.Затем происходит переключение графического процессора назад и вперед между выполнением каждого набора потоков, в результате чего каждый цикл выполнения занимает неоптимальную занятость.

Чтобы улучшить это, постарайтесь убедиться, что потоки, которые будут выполняться вместе вДеформация (32 на всех картах NVIDIA сегодня ... я думаю) будет проходить по одному и тому же пути через код ядра.Иногда сортировка входных данных так, что подобные данные обрабатываются вместе, работает.Кроме того, может помочь добавление барьера в стратегических местах в коде ядра.Если потоки деформации вынуждены расходиться, барьер будет следить за тем, чтобы после того, как они снова достигли общего кода, они ожидали друг друга, а затем возобновили выполнение с полной загрузкой (для этой деформации).Просто знайте, что барьер должен быть затронут всеми потоками, иначе вы вызовете тупиковую ситуацию.

Я не могу обещать, что это весь ваш ответ, но это кажется большой проблемойдля вашего кода указаны числа, указанные в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...