Подтвердить что ты не робот

Вопросы о глобальном и локальном размере работы

Поиск по форумам NVIDIA я нашел эти вопросы, которые также представляют для меня интерес, но никто не ответил им за последние четыре дня или так. Вы можете помочь?

Оригинальная публикация форума

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

  • Должен ли global_work_size быть меньше, чем CL_DEVICE_MAX_WORK_ITEM_SIZES? На моей машине CL_DEVICE_MAX_WORK_ITEM_SIZES= 512, 512, 64.

  • Является ли CL_KERNEL_WORK_GROUP_SIZE рекомендуемым work_group_size для используемого ядра?

    • Или это единственный work_group_size, который позволяет использовать GPU? На моей машине CL_KERNEL_WORK_GROUP_SIZE= 512
  • Нужно ли делиться с рабочими группами или иметь только один, но не указывая local_work_size?

    • К чему я должен обратить внимание, когда у меня есть только одна рабочая группа?
  • Что означает CL_DEVICE_MAX_WORK_GROUP_SIZE? На моей машине CL_DEVICE_MAX_WORK_GROUP_SIZE= 512, 512, 64

    • Означает ли это, что у меня может быть одна рабочая группа размером до CL_DEVICE_MAX_WORK_ITEM_SIZES?
  • Имеет ли global_work_size делитель CL_DEVICE_MAX_WORK_ITEM_SIZES? В моем коде global_work_size= 20.

4b9b3361

Ответ 1

В общем случае вы можете выбрать global_work_size как можно больше, в то время как local_work_size является ограничением базовым устройством/оборудованием, поэтому все результаты запроса будут сообщать вам возможные размеры для local_work_size вместо global_work_size. единственным ограничением для global_work_size является то, что он должен быть кратным local_work_size (для каждого измерения).

Размеры рабочей группы определяют размеры рабочих групп, поэтому, если CL_DEVICE_MAX_WORK_ITEM_SIZES - 512, 512, 64, это означает, что ваш local_work_size не может быть больше, чем 512 для измерения x и y и 64 для z-измерения.

Однако существует также ограничение на размер локальной группы в зависимости от ядра. Это выражается через CL_KERNEL_WORK_GROUP_SIZE. Ваш кумулятивный workgoupsize (как в продукте всех измерений, например 256, если у вас есть localsize 16, 16, 1), не должен быть больше этого числа. Это связано с тем, что ограниченные аппаратные ресурсы должны быть разделены между потоками (из ваших результатов запроса я предполагаю, что вы программируете на графическом процессоре NVIDIA, поэтому количество локальной памяти и регистров, используемых потоком, ограничивает количество потоков, которые могут быть выполняются параллельно).

CL_DEVICE_MAX_WORK_GROUP_SIZE определяет максимальный размер рабочей группы таким же образом, как CL_KERNEL_WORK_GROUP_SIZE, но конкретный для устройства вместо ядра (и он должен быть скалярным значением aka 512).

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

Однако следует отметить, что использование только одной рабочей группы, как правило, не является хорошей идеей производительности (и почему использование OpenCL, если производительность не вызывает беспокойства). В общем случае рабочая группа должна выполняться на одном вычислительном блоке, в то время как у большинства устройств будет больше одного (у современных процессоров есть 2 или более, по одному для каждого ядра, в то время как современные графические процессоры могут иметь 20 или более). Более того, даже один вычислительный блок, на котором выполняется ваша рабочая группа, может не полностью использоваться, так как несколько рабочих групп могут выполняться на одном вычислительном блоке в стиле SMT. Для оптимального использования графических процессоров NVIDIA вам нужны потоки 768/1024/1536 (в зависимости от поколения, что означает G80/GT200/GF100), выполняемые на одном вычислительном блоке, и пока я не знаю номера для amd прямо сейчас, они находятся в такая же величина, поэтому хорошо иметь более одной рабочей группы. Кроме того, для графических процессоров обычно рекомендуется иметь рабочие группы, в которых по меньшей мере 64 потока (и количество потоков делится на 32/64 (nvidia/amd) на рабочую группу), поскольку в противном случае вы снова будете иметь пониженную производительность (32/64 - это минимальная грануляция для выполнения на gpus, поэтому, если у вас меньше элементов в рабочей группе, она будет выполняться как потоки 32/64, но отбрасывать результаты из неиспользуемых потоков).