Выполняются ли рабочие группы OpenCL одновременно?
Насколько я понимаю, каждая рабочая группа выполняется на GPU, а затем выполняется следующая.
К сожалению, мои наблюдения приводят к выводу, что это неверно.
В моей реализации все рабочие группы совместно используют большой глобальный буфер памяти.
Все рабочие группы выполняют операции чтения и записи в различные позиции этого буфера.
Если ядро работает непосредственно с ним, то никаких конфликтов не возникает.
Если рабочая группа загружает фрагмент в локальную память, выполните некоторые вычисление и копирование результата обратно, глобальная память повреждается другими рабочими группами.
Так как же мне избежать такого поведения?
Могу ли я каким-то образом приказать OpenCL выполнять только одну рабочую группу сразу или изменить порядок выполнения, чтобы я каким-то образом не получал конфликтов?
3 ответов:
Ответ заключается в том, что это зависит. Вся рабочая группа должна выполняться одновременно (хотя и не обязательно параллельно) на устройстве, по крайней мере при наличии барьеров, поскольку рабочая группа должна иметь возможность синхронизировать и обмениваться данными. Нет правила, которое говорит, что рабочие группы должны быть параллельными, но нет правила, которое говорит, что они не могут. Обычно аппаратное обеспечение размещает одну рабочую группу на одном вычислительном ядре. Большинство аппаратных средств имеет несколько ядер, каждое из которых будет иметь рабочую группу, и много оборудования также разместит несколько рабочих групп на одном ядре, если есть доступная емкость.
Вы не можете контролировать порядок выполнения рабочих групп. Если вы хотите, чтобы они сериализовались, вам лучше запустить только одну рабочую группу и написать цикл внутри, чтобы сериализовать серию рабочих блоков в той же рабочей группе. Это часто хорошая стратегия в целом даже с несколькими рабочими группами.
Если вы действительно хотите только одну рабочую группу в со временем, однако, вы, вероятно, будете использовать только крошечную часть оборудования. Большинство аппаратных средств не могут распределить одну рабочую группу по всему устройству - так что если вы застряли на одном ядре на 32-ядерном GPU, вы не получите много пользы от устройства.
Вам нужно установить глобальный размер и размеры для одной рабочей группы и поставить в очередь новый NDRange для каждой группы. По сути, разбиение вызова вашего ядра на множество более мелких вызовов. Убедитесь, что ваша очередь команд не разрешает выполнение вне очереди, так что вызовы ядра блокируются.
Это, скорее всего, приведет к снижению производительности, но вы получите доступ к выделенной глобальной памяти, который вы ищете.
Да, группы могут выполняться параллельно.; обычно это очень хорошая вещь. вот связанный с этим вопрос.
Количество рабочих групп, которые могут быть одновременно запущены на ComputeUnit (AMD) или SMX (Nvidia), зависит от наличия аппаратных ресурсов GPU, важными из которых являются векторные регистры и память уровня рабочей группы** (называемая LDS для AMD и общей памятью для Nvidia). Если вы хотите запустить только одну рабочую группу на CU / SMX, убедитесь, что рабочая группа потребляет большую часть этих ресурсов и блокирует дальнейшие рабочие группы на том же CU/SMX. Однако у вас по-прежнему будут другие рабочие группы выполнение на другие уе/SMXs - графический процессор, как правило, имеет несколько из них. Мне не известны какие-либо API, который позволяет закрепить ядра на один КР/сульфаметоксазола.
* * это также зависит от количества одновременных волновых фронтов / искажений, которые может обрабатывать планировщик.
Comments