Запуск многомерного ядра в openCL не работает - PullRequest
0 голосов
/ 05 апреля 2019

Я пытаюсь запустить openCL в 3-х измерениях следующим образом:

size_t globalWorkSize[3] = {32, 3, 3};   
size_t localWorkSize[2] = {32, 32};   

err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalWorkSize, localWorkSize,
                                                          0, NULL, NULL);

Но только 32 потока запускаются.

Также есть ли способ найти эквивалентность потоков Cuda n openCL?

Может кто-нибудь, пожалуйста, помогите. Спасибо.

Ответы [ 3 ]

3 голосов
/ 05 апреля 2019

Глобальный размер работы определяет, сколько задач запущено.Т.е. сколько раз будет вызываться функция ядра в общей сложности.

Локальный рабочий размер разделяет глобальный рабочий размер на локальные группы, чтобы они могли совместно использовать память и барьеры.

Причина, по которой только 32 потоказапущен из-за 1 в

clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalWorkSize, localWorkSize,
                                                          0, NULL, NULL);

Вы указали, что ядро ​​является 1D, а не 3D, и OpenCL не будет смотреть за первыми значениями этих массивов рабочих размеров.Кроме того, локальные размеры работы должны делить глобальные размеры работы - поэтому все локальные группы будут иметь одинаковый размер.Например, глобальный {32, 3, 3} может иметь локальные размеры:

  1. {32,3,3}, что делает одну локальную группу = целое ядро ​​может совместно использовать память.
  2. {32,1,1} создаст 3 локальные группы,каждая с размером {32,1,1}.
  3. Как правило, любая группировка {32/X,3/Y,3/Z} будет работать тогда и только тогда, когда числа можно будет разделить равномерно и сформировать X Y Z локальных групп.

CUDA против рабочих групп OpenCL

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

Сетка CUDA состоит из блоков потоков, и при вызове ядра необходимо указывать размеры сетки в виде блоков потоков и размеры блоков в терминах потоков.Но при вызове ядра OpenCL необходимо указать глобальную рабочую группу в терминах рабочих элементов, а не локальных групп .Это причина того, что глобальный размер группы должен делиться на размеры локальной группы (во всех измерениях).Локальные группы задаются в терминах рабочих элементов, что снова делает их эквивалентными блокам CUDA.

Пример:

Ядро CUDA с блоком из {32,32,1} организованных потоковв сетку из {32,3,3} потоковых блоков эквивалентно локальной рабочей группе из {32,32,1} рабочих элементов и глобальной рабочей группе из {32*32,3*32,3*1}={1024,96,3} рабочих элементов.

TLDR:

локальная группа = блок потока

глобальная группа = сетка * блок потока

1 голос
/ 05 апреля 2019

Я задал похожий вопрос здесь: OpenCL global worskize по-разному интерпретируется в iGPU Haswell & Kabylake Очевидно, что GlobalWorkSize и localWorkSize должны иметь те же измерения, что и «work_dim» в https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/clEnqueueNDRangeKernel.html

0 голосов
/ 05 апреля 2019
clEnqueueNDRangeKernel(queue, kernel, /*this is the number os dimensions: */ 3, NULL, globalWorkSize, localWorkSize, 0, NULL, NULL);

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

Кто-то поправит меня, если я ошибаюсь, потому что я никогда не использовал более одного измерения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...