2017-02-15 6 views
1

Как известно, существуют WARP (в CUDA) и WaveFront (в OpenCL): http://courses.cs.washington.edu/courses/cse471/13sp/lectures/GPUsStudents.pdfЕсть ли гарантия, что все потоки в WaveFront (OpenCL) всегда синхронизированы?

enter image description here

4,1. SIMT Архитектура

...

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

Архитектура SIMT сродни SIMD (Single Instruction, Multiple Data) организациям векторов в том, что одна команда управляет несколькими элементами обработки. Ключевым отличием является то, что организации SIMD vector раскрывают ширину SIMD для программного обеспечения, тогда как инструкции SIMT определяют поведение выполнения и ветвления одного потока .

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


Т.е. мы знаем, что:

  • нити в WARP (CUDA) - это SIMT-нити, которые всегда выполняет те же инструкции, в каждый момент времени и всегда будут оставаться синхронизированы - т.е.Нити WARP такие же, как lanes of SIMD (на CPU)

  • нити в WAVEFRONT (OpenCL) - это темы, которые всегда выполняется параллельно, но не обязательно все нити выполняют ту же самую инструкцию, и не обязательно все потоки синхронизированы

Но есть ли гарантия того, что все нити в WAVEFRONT всегда синхронизированы таким образом, как потоки в WARP или как полосы в SIMD?


Заключение:

  1. WAVEFRONT-нитка (элементы) всегда синхронизирована - шаг блокировки: «волновой фронт выполняет ряд рабочих-элементы в замке шага по отношению друг к другу. "
  2. WaveFront отображается на SIMD-блоке: "все рабочие элементы в волновом фронте идут к обеим путям управления потоком"
  3. И.Э. каждый WaveFront-нить (пункт) отображается на SIMD-полосная

страница-20: http://developer.amd.com/wordpress/media/2013/07/AMD_Accelerated_Parallel_Processing_OpenCL_Programming_Guide-rev-2.7.pdf

Глава 1 OpenCL Архитектура и AMD Accelerated Parallel Processing

1.1 Терминология

...

Волновые фронты и рабочие группы - две концы epts, относящихся к вычислениям ядер , которые обеспечивают параллельность данных. A wavefront выполняет ряд рабочих элементов в шаг блокировки относительно каждого другой. Шестнадцать рабочих элементов выполняются параллельно по вектору единица, а весь волновой фронт покрыт четырьмя тактами. Это - это самый низкий уровень, на который может влиять управление потоком. Это означает, что если два рабочих элемента внутри волнового фронта идут по расходящимся путям потока управления, все рабочие элементы в волновом фронте идут по обоим путям потока управление.

Это верно: http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_OpenCL_Programming_Optimization_Guide2.pdf

  • (страница-45) Глава 2 OpenCL Производительность и оптимизация для GCN устройств
  • (страница-81) Глава 3 OpenCL Performance и оптимизация для Приборы на вечнозеленых и северных островах
+0

также серии HD5000 и HD4000 amd имеют SIMD ширину 4, но размер волнового фронта 64. –

ответ

0

Во-первых, вы можете запросить несколько значений:

CL_DEVICE_WAVEFRONT_WIDTH_AMD 
CL_DEVICE_SIMD_WIDTH_AMD 
CL_DEVICE_WARP_SIZE_NV 
CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 

, но только от принимающей стороны, как я знаю.

Предположим, что эти запросы возвращены 64, и ваш вопрос придает важность неявной синхронизации потоков.

Что делать, если кто-то выбирает локальный диапазон = 4?

Поскольку opencl абстрактные аппаратные часы от разработчика, вы не можете знать, какой фактический размер SIMD или WAVEFRONT является результатом выполнения ядра во время выполнения.

Например, AMD NCU имеет 64 шейдера, но имеет 16-экранный SIMD, 8-широкий SIMD, 4-широкий SIMD, 2-широкий SIMD и даже два скалярных устройства внутри одного и того же вычислительного блока.

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

Или GCN CU, который имеет 4x16 SIMD в нем, может выделять 1 поток на SIMD, делая все 4 потока полностью независимыми. Если они все проживают в одном SIMD, вам повезло. Нет гарантии, что «до» выполнения ядра. Даже после того, как вы знаете, следующее ядро ​​может отличаться, поскольку нет гарантии выбора одного и того же распределения SIMD (фоновые ядра, программное обеспечение для визуализации 3D, даже ОС может помещать пузырьки в трубопроводы)

Нет гарантий командования/намекания/запрос N потоков для запуска как один SIMD или тот же WARP до запуска ядра. Затем в ядре нет команды для получения индекса волнового фронта потока, как get_global_id (0). Затем после ядра вы не можете полагаться на результаты массива, так как следующее выполнение ядра может не использовать одинаковые SIMD для одних и тех же элементов. Даже некоторые элементы из других волновых фронтов могут быть заменены элементом с текущего волнового фронта только для оптимизации драйвером или аппаратным обеспечением (в последнее время nvidia имеет loadbalancer и мог бы это делать, также NCU amd может использовать подобную вещь в будущем)

Даже если вы угадываете правильную комбинацию потоков на SIMD на вашем оборудовании и драйвере, это может быть совершенно другим на другом компьютере.


Если его для точки зрения производительности, можно попробовать:

  • нулевой ветвь в коде ядра
  • нулю ядро ​​работает в фоновом режиме
  • видеокарта не используется для выхода монитора
  • gpu не используется для некоторых программ визуализации

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

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

Затем те потоки, которые работают в одном SIMD, будут вести себя синхронно. Но вы можете не знать, какие из них есть, и какие SIMD.

Для примера с 4 потоками использование float16 для всех вычислений может позволить драйверу использовать 16-разрядные SIMD из AMD GCN CU для вычисления, но тогда они больше не являются потоками, а только переменными. Но это должно улучшить синхронизацию данных, чем потоков.

Есть более сложные ситуации, такие как:

  • 4 нитей в одном SIMD но один расчет потоков генерирует некоторое значение NaN и делает дополнительные нормализации (с 1-2 цикла может быть) по этому вопросу. 3 другим должны ждать завершения, но он работает независимо от замедления данных.

  • 4 потока в одном волновом фронте находятся в петле и один из них застрял навсегда. 3 из них ждут, что четвертый закончен навсегда, или водитель обнаружит и переместит его в другой свободный пустой SIMD? Или четвертый один ждет еще 3 одновременно, потому что они тоже не двигаются!

  • 4 потока, выполняющих атомные операции, один за другим.

  • GPU серии HD5000 AMD имеет ширину SIMD 4 (или 5), но размер волнового фронта 64.

+0

Спасибо!Означает ли это, что WaveFront не гарантирует, что все потоки WaveFront выполняют одну общую инструкцию за раз, поскольку половина WaveFront может быть выполнена на одном SIMD-модуле и другой половине на другом SIMD-устройстве, или половина WaveFront может быть выполняется последовательно на одной SIMD-блоке малой ширины. Но WaveFront гарантирует блокировку, что ** первая половина не может отстать от второй половины более чем на 1 команду **, поэтому мой код не может сказать разницы, потоки WaveFront выполняются параллельно или нет. https://hsto.org/files/824/593/10e/82459310e0d74b91b8715005b8f04352.jpg – Alex

+1

Существует «не должно отставать от более чем 1 инструкции», но оно должно быть под недивергентным кодом. Nvidia может делать это «вычислять обе стороны», в то время как amd может делать это «вычислять обе стороны один за другим» с отверстиями в нем. –

+0

И никто не пишет, что если nvidia вычисляет «else» часть «if» тайно на другом SIMD. –

1

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

Один процесс обработки потока похож на одно ядро ​​процессора. Он будет повторять одну 16-кратную векторную инструкцию четыре раза, чтобы выполнить 64 так называемых «потока» в волновом фронте. На самом деле один волновой фронт - это больше поток, чем тот, который мы называем потоком на графическом процессоре.

+0

только что протестировал вывод llvm некоторого ядра float4, он имеет 4x количество операций для каждого элемента вектора. поэтому вы правы только по 1 SIMD-элементу на поток. Но использование вектора облегчает компилятору использование векторного alu вместо скалярного alu или лучше распределяет рабочие элементы. –

+0

@huseyintugrulbuyukisik В векторной операции в GCN нет строчки для «потока». Когда значение переменной согласовано на волновом фронте, компилятор выберет скалярное alu, чтобы сохранить регистр vecter, иначе вектор alu всегда используется. GCN сильно отличается от проницаемой архитектуры. Использование векторных типов иногда помогает компилятору использовать векторную загрузку/хранение, но в течение большей части времени компилятор может сделать это правильно даже без использования векторных типов. – BlueWanderer

+0

Спасибо! Можете ли вы пояснить разницу между ** 1. ** «старыми компиляторами, вы можете опустить синхронизацию, если ваша локальная группа содержит только один волновой фронт» и ** 2. ** «Новые компиляторы будут опускать синхронизацию для вас, если ваша локальная группа содержит только один волновой фронт ». В обоих случаях я использую только один волновой фронт, и синхронизация опускается, но в чем разница? – Alex