OpenCL: концепция рабочей группы

Я не понимаю цели Рабочих групп в OpenCL.

Я понимаю, что это группа рабочих элементов (предположительно, аппаратных потоков), которые выполняются параллельно.

Однако почему существует необходимость в более грубом подразделении? Разве не было бы хорошо иметь только сетку нитей (и, де-факто, только один W-G)?

Если рабочая группа точно соответствует физическому ядру? Например, для карты TESLA c1060 установлено 240 ядер. Как будут отображены рабочие группы?

Кроме того, насколько я понимаю, рабочие элементы внутри рабочей группы могут быть синхронизированы благодаря заборам памяти. Могут ли рабочие группы синхронизировать или даже нужны? Они разговаривают друг с другом через разделяемую память или это только для рабочих элементов (не уверен в этом)?

Ответы

Ответ 1

Часть путаницы здесь, я думаю, сводится к терминологии. То, что люди GPU часто называют ядрами, на самом деле не так, и то, что люди GPU часто называют потоками, только в определенном смысле.

Сердечники Ядро в маркетинговых терминах графического процессора может относиться к чему-то вроде ядра ЦП или может относиться к одной полосе SIMD-модуля - фактически, один процессор x86 с одним ядром будет иметь четыре ядра этого более простого типа. Вот почему количество ядер GPU может быть настолько высоким. Это не очень справедливое сравнение, вам нужно разделить на 16, 32 или аналогичное число, чтобы получить более сопоставимый подсчет ядра.

Работа-элементы Каждый рабочий элемент в OpenCL представляет собой поток с точки зрения его потока управления и его модели памяти. Аппаратное обеспечение может запускать несколько рабочих элементов в одном потоке, и вы можете легко представить это, представив четыре рабочих элемента OpenCL, работающих на отдельных дорожках вектора SSE. Это будет просто обманом компилятора, который достигнет этого, и на графических процессорах он, как правило, представляет собой смесь обмана и аппаратной поддержки компилятора. OpenCL 2.0 фактически раскрывает эту концепцию базового потокового оборудования через подгруппы, поэтому существует еще один уровень иерархии, с которым нужно иметь дело.

Работа-группы Каждая рабочая группа содержит набор рабочих элементов, которые должны быть способны добиться прогресса в присутствии барьеров. На практике это означает, что это набор, все состояние которого может существовать одновременно, так что, когда встречается примитив синхронизации, в переключении между ними имеется небольшая накладная плата, и есть гарантия, что коммутатор возможен.

Рабочая группа должна сопоставляться с единым вычислительным блоком, что реально означает, что вся рабочая группа подходит для одного объекта, который люди ЦП будут называть ядром - CUDA будет называть его многопроцессорным (в зависимости от поколения), AMD вычислительная единица и другие имеют разные имена. Эта локальность выполнения приводит к более эффективной синхронизации, но также означает, что набор рабочих элементов может иметь доступ к локально построенным блокам памяти. Ожидается, что они будут часто связываться, или барьеры не будут использоваться, и для эффективного использования этого сообщения могут быть локальные кэши (похожие на процессор L1) или память с блокнотной памятью (локальная память в OpenCL).

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

Многое из-за истории, а не дизайна. Аппаратное обеспечение GPU давно разработано для создания векторных потоков и назначает их исполнительным блокам таким образом, чтобы оптимально обрабатывать треугольники. OpenCL выпадает из обобщения того, что аппаратное обеспечение полезно для других вещей, но не обобщает его настолько, что оно становится неэффективным для реализации.

Ответ 2

Уже есть много хороших ответов, для дальнейшего понимания терминологии OpenCL в этой статье действительно очень хорошо описывается все концепции.

Ответ 3

Одно из преимуществ рабочих групп заключается в том, что они позволяют использовать общую локальную память в качестве кэша, определяемого программистом. Значение, считываемое из глобальной памяти, может быть сохранено в общей локальной рабочей группе рабочей группы, а затем быстро получить доступ к любому рабочему элементу в рабочей группе. Хорошим примером является игра жизни: каждая ячейка зависит от себя и от нее. Если каждый рабочий элемент прочитает эту информацию, вы получите 9-кратную глобальную память. Используя рабочие группы и общую локальную память, вы можете приближаться к 1х глобальным чтениям памяти (только подход, поскольку на краях имеется избыточное чтение).

Ответ 4

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

Кроме того, как правило, устройства OpenCL используют расширения Single Instruction Multiple Data (SIMD) для достижения хорошего parallelism. Одну рабочую группу можно запускать параллельно с расширениями SIMD.

 Should a Work-Group exactly map to a physical core ?

Я думаю, что единственный способ найти самый быстрый размер рабочей группы - попробовать разные размеры рабочей группы. Также можно запросить CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE с устройства с помощью clGetKernelWorkGroupInfo. Самый быстрый размер должен быть кратным.

 Can work-groups synchronize or is that even needed ?

Рабочие группы не могут быть синхронизированы. Таким образом, между ними нет зависимостей между данными, и их также можно запускать последовательно, если это считается самым быстрым способом их запуска. Для достижения такого же результата, как синхронизация между рабочими группами, ядро ​​необходимо разбить на несколько ядер. Переменные могут передаваться между ядрами с помощью буферов.