У меня есть трехмерный вектор F
, который в настоящее время заполняется последовательно следующим образом:
// for each particle
for(int p = 0; p < pmax; p++) {
// and each dimension (n x m x o)
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) {
for(int k = 0; k < o; k++) {
// do some calulations depending on p, i, j and k and add onto F
F[i][j][k] += p * i * j * k;
}
}
}
}
Значение F вычисляется постепенно для каждой частицы.
Теперь я хотел чтобы ускорить процесс с использованием OpenCL. Моей первой попыткой было распараллелить внутренние циклы с помощью 3D-Range-Kernel, который вызывается для каждой частицы. Это действительно хорошо работает, но даже медленнее на GPU, чем на CPU (без применения каких-либо оптимизаций - например, F
копируется с хоста на GPU и обратно в каждую итерацию).
Во второй попытке я попытался распараллелить внешний l oop, что (я думаю) является лучшей идеей, чем первая попытка, поскольку ожидается, что pmax
будет намного больше, чем m * n * o
. Из того, что я прочитал, я думаю, что проблему можно решить с помощью параллельного уменьшения суммы, чего можно привести множество примеров. Однако для этого подхода мне нужно иметь копию F
для каждого потока (или рабочего элемента), который не помещается в памяти (получая CL_OUT_OF_RESOURCES
здесь).
Мой вопрос сейчас : возможно ли даже распараллелить такую инкрементную сумму, не сохраняя F
в памяти несколько раз для нескольких частиц? Если да, как бы выглядел хороший подход? Стоит ли вместо этого придерживаться своей первой попытки и попытаться оптимизировать ее?
Обратите внимание, что я новичок в OpenCL и не очень разбираюсь в методах распараллеливания в целом. Буду признателен за любые подсказки или ссылки на полезные лекции или примеры, спасибо!
Кстати, мои сеансы поиска в Google по этой теме c только приведут меня к вычислению суммы префикса.