2011-07-13 6 views
7

У меня есть вопрос о том, как графические процессоры выполняют синхронизацию. Как я знаю, когда варп сталкивается с барьером (при условии, что он находится в OpenCL), и он знает, что другие перекосы той же группы еще не были там. Поэтому он должен ждать. Но что именно делает этот варп в течение времени ожидания? Является ли он все еще активным декомпрессивом? Или он сделает какие-то нулевые операции?Синхронизация в графических процессорах

Как я заметил, когда у нас есть синхронизация в ядре, количество инструкций увеличивается. Интересно, что является источником этого приращения. Является ли синхронизация разбитой на несколько меньших инструкций GPU? Или потому, что незанятые перекосы выполняют некоторые дополнительные инструкции?

И, наконец, я сильно удивляюсь, зависит ли стоимость, добавленная синхронизацией, по сравнению с одной без синхронизации (скажем, барьер (CLK_LOCAL_MEM_FENCE)), количество варпов в рабочей группе (или в потоковом блоке)?

ответ

7

Активный warp - это объект, который находится на SM, то есть все ресурсы (регистры и т. Д.) Были выделены, и warp доступен для выполнения, обеспечивая его планирование. Если warp достигает барьера перед другими перекосами в той же самой ветке/рабочей группе, он все равно будет активен (он все еще остается на SM, и все его регистры все еще действительны), но он не будет выполнять никаких инструкций, поскольку это не готовы к планированию.

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

Стоимость барьера очень зависит от того, что делает ваш код, но каждый барьер вводит пузырь, где все деформации должны (эффективно) простаивать, прежде чем они все снова начнут работать, поэтому, если у вас очень большой блок потоков/work-group, то, разумеется, есть потенциально больший пузырь, чем с небольшим блоком. Влияние пузыря зависит от вашего кода - если ваш код очень привязан к памяти, тогда барьер будет вызывать задержки памяти, прежде чем они могут быть скрыты, но если они более сбалансированы, то это может иметь менее заметный эффект.

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

+0

Спасибо за подробный ответ. Было бы неплохо, если бы вы могли поделиться некоторыми документами, из которых вы получили знания. Я хотел бы привести в своих исследованиях. Не могли бы вы объяснить, почему ядра, связанные с памятью, вызывают задержки памяти? Как я понимаю, запрос памяти рядом с синхронизацией (появляется перед синхронизацией), которая должна быть скрыта при некоторых вычислениях, будет остановлена ​​до тех пор, пока данные не поступят. Правильно ли это? С другой стороны, если ядро ​​не является mem-bound, что делает синхронизация? латентность конвейера? (не предполагалось никаких расхождений, и да, что все это делает с расхождениями?) – Zk1001

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