2012-02-23 1 views
3

Когда я запускаю профайлер против моего кода, часть продукции является:CUDA, профилированный, достигли очень низкого уровня; как диагностировать?

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, перемещение данных в текстуры и т.д.

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

Редактировать 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 и ветвящиеся статистики).

+0

Было бы интересно посмотреть, сколько времени потрачено на чтение и запись данных, а также на некоторый код ядра, чтобы узнать, что происходит. Не уверены в отсутствующих файлах csv, если они могут быть проблемой. EDIT: Другой интересный выход из профилировщика - это расходящиеся ветви, а также неизолированные и объединенные чтения/записи памяти. – martiert

+0

Это данные, которые вы ищете? Значения не кажутся мне необоснованными; конечно, не нравится что-то при занятости 0,02. –

+1

Плохое количество счетчиков для глобальной пропускной способности чтения/записи недоступно. Это странно, но помогло бы. Можете ли вы также указать код ядра? Я понятия не имею, что вы делаете ядро, или о том, как много работает.Я думаю, что у вас нет большого количества данных, хотя, возможно, это будет небольшая работа для GPU, если алгоритм не требует много работы. – martiert

ответ

3

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

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

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

+0

Спасибо за обновление/уточнение. Полезно знать о правиле ~ 5 сек. :) Я переключил это на принятый ответ. –

0

Похоже (большая часть) ваш вопрос здесь:

Control flow divergence(%): 96.88

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

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

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

+0

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

+1

Это может быть проблемой производительности, но это не имеет ничего общего с проблемой занятости, если только, как указал Грег большинство перекосов выходят далеко раньше, чем одна длинная деформация. – harrism

3

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

Достигнутое заполнение - это мера (active_warps/active_cyles)/max_warps_per_sm.

Достигнутое заполнение .02 подразумевает, что на SM активно только 1 перекос. Учитывая запуск 10000 перекосов (2500 блоков * 128 потоков/WARP_SIZE), это может произойти только в том случае, если у вас есть чрезвычайно расходящийся код, где все перекосы, за исключением 1, немедленно выходят и 1 warp работает очень долго. Также маловероятно, что вы могли бы достичь 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

active_warps и active_cycles для меня 4294967295, AKA 2 ** 32-1. Похоже, я ударил максит. :/1.0/48 ~ = 0.02 Я приму это, как только я получу полную информацию, написанную. Благодаря! –

+0

Чтобы убедиться, что у вас есть хороший опыт работы с инструментами, было бы здорово, если бы вы могли попробовать выпуск 4.1 и сообщить нам, если результаты будут лучше! – harrism

+0

Мы не планировали касаться установки CUDA до Кеплера. :/Будет ли обновление CUDA совпадать с Kepler? И если да, есть ли еще время для внесения изменений? (Я бы предположил, что корабль давно отплыл, но, возможно, нет;) –

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