Я занимаюсь продолжением своей первой проблемы, поясненной на this link.Способ выполнения окончательной суммы с уменьшением
Напоминаю, что я хотел бы применить метод, который может выполнять множественные сокращения суммы с помощью OpenCL (мое устройство GPU поддерживает только OpenCL 1.2). Мне нужно вычислить суммарное уменьшение массива для проверки критерия сходимости для каждой итерации основного контура,
В настоящее время я сделал версию только для одного уменьшения суммы (например, одной итерации ). В этой версии и для простоты я использовал последовательный цикл ЦП, чтобы вычислить сумму каждой частичной суммы и получить окончательное значение суммы.
Из ваших рекомендаций в моем прецеденте моя проблема в том, что я не знаю, как выполнить окончательную сумму, вызвав вторую функцию NDRangeKernel
(т. Е. Выполняя второй раз код ядра).
Действительно, со вторым вызовом я всегда сталкиваюсь с той же проблемой для получения суммы частичных сумм (сам рассчитывается при первом вызове NDRangeKernel
): это кажется рекурсивной проблемой.
Давайте возьмем пример из приведенного выше рисунка: если размер входного массива 10240000
и WorkGroup size
16
это, мы получаем 10000*2^10/2^4 = 10000*2^6 = 640000 WorkGroups
.
Итак, после первого звонка я получаю 640000 partial sums
: как бороться с окончательной суммой всех этих частичных сумм? Если я вызову еще раз код ядра с, например, WorkGroup size = 16
и глобальным size = 640000
, я получу nWorkGroups = 640000/16 = 40000 partial sums
, поэтому мне нужно еще раз вызвать код ядра и повторить этот процесс до nWorkGroups < WorkGroup size
.
Может быть, я не очень хорошо понимаю, второй этап, в основном это часть кода ядра от «снижения двухступенчатой» (on this link, I think this is the case of searching for minimum into input array)
__kernel
void reduce(__global float* buffer,
__local float* scratch,
__const int length,
__global float* result) {
int global_index = get_global_id(0);
float accumulator = INFINITY;
// Loop sequentially over chunks of input vector
while (global_index < length) {
float element = buffer[global_index];
accumulator = (accumulator < element) ? accumulator : element;
global_index += get_global_size(0);
}
// Perform parallel reduction
...
Если кто-то может объяснить, что это выше фрагмент кода ядра код делает.
Есть ли связь со вторым этапом редукции, т. Е. Окончательная сумма?
Не стесняйтесь спрашивать меня, если вы не поняли мою проблему.
Благодаря
Я думаю, что это вычисление 640000 рабочих групп неверно. У меня также были проблемы с пониманием этой статьи в первую очередь. [Этот ответ] (http://stackoverflow.com/a/10975985/3182664) помог немного: он ясно показывает, что для каждой рабочей группы будет * один * результат. Даже большое количество элементов сводится к «немногим» элементам, которые затем могут быть уменьшены на хосте. – Marco13
@ Marco13 почему вы думаете, что вычисление 640000 рабочих групп не является правильным? – youpilat13
Я думаю, что вы можете определить «произвольный» размер рабочей группы. Но для 10240000 элементов вы можете, например, использовать 64 рабочих группы, которые будут вычислять 64 результата, где каждая рабочая группа будет заботиться об элементах 10240000/64 (но, по общему признанию, мне пришлось бы обновить мои воспоминания здесь, чтобы сделать более конкретное заявление - извините, поэтому я только прокомментировал) – Marco13