Во-первых, по умолчанию вы должны использовать только 1 измерение для своих ядер. Для некоторых задач требуется 2 или 3 измерения (как правило, обработка изображений), но если вы явно не работаете над одной из этих задач, вам, вероятно, не будет выгодно пытаться разделить вещи между несколькими измерениями, поскольку преимущества в основном связаны с кодом. организация, а не о производительности.
Таким образом, остается вопрос о том, как разделить рабочие элементы среди местных групп. Учитывая размер задачи N
рабочих элементов, у вас есть несколько вариантов их разделения на локальные группы.
Самое простое решение - просто указать N
рабочих элементов и позволить водителю решить, как разделить эти рабочие элементы между группами.
size_t work_items = 164052;
clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, &work_items, nullptr, 0, nullptr, nullptr);
Если вы программируете для конкретной среды, в которой заранее известно идеальное количество локальных рабочих элементов (часто 32 или 64 для архитектур NVidia / AMD), вы можете добиться более высокой производительности, если заставить количество рабочих элементов соответствовать кратное этому числу.
size_t work_items = 164052;
size_t LOCAL_SIZE = 64;
work_items += LOCAL_SIZE - (work_items % LOCAL_SIZE);
clEnqueueNDRangeKernel(queue, kernel, 1, nullptr, &work_items, &LOCAL_SIZE, 0, nullptr, nullptr);
Обратите внимание, однако, что для этого необходимо добавить проверку в код ядра, чтобы предотвратить обработку на рабочих элементах, которые на самом деле не существуют, или чтобы вы добавили в свои буферы пространство для фиктивных элементов.
kernel void main(..., int N) {
if(get_global_id(0) >= N) return;
...
}