Как оптимизировать запись в гистограмму в OpenCL (разброс / сбор)? - PullRequest
2 голосов
/ 04 ноября 2019

Я пишу что-то похожее на систему частиц в OpenCL. Все частицы имеют положение и цвет, который рассчитывается на лету. В конце всех расчетов я хочу показать все частицы на экране. Для этого я хочу добавить все значения частиц (многие миллионы из них) к двухмерной гистограмме, чтобы гистограмма была большой (скажем, 1920 * 1080).

enter image description here Обратите внимание, что все компоненты, включая альфа-компонент, просто суммируются.

В настоящее время я просто использую буфер, состоящий изuint4 (или float4) для этого, который является (огромным) узким местом в моем приложении, так как это операция разброса / сбора в глобальной памяти:

//Obviously hugely simplified for your reading pleasure
for (int i = 0; i < 1000; i++) {
    float calculatedYPixel = random() * 1080;
    float calculatedXPixel = random() * 1920;
    uint4 calculatedColour = (uint4) (0, 27, 244, 55); //something random as well
    histogram[(int) calculatedYPixel * histogramSize.x + (int) calculatedXPixel] += calculatedColour;
}

Есть ли способ ускорить это? ? В настоящее время я использую OpenCL 1.2, но мне также было бы интересно услышать о решениях, включающих OpenCL 2, CUDA или OpenGL.

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

Мне также было любопытно, можно ли здесь использовать ROP (выходные блоки рендеринга), поскольку их функция выглядит довольно схожей с этим типом вычислений. Из некоторых источников кажется, что буфер рендеринга на графическом процессоре может быть оптимизирован, например, для доступа на запись.

1 Ответ

1 голос
/ 05 ноября 2019

Есть ли способ ускорить это?

Как часто, "как мы реализуем этот последовательный алгоритм на GPU?"это, вероятно, неправильный вопрос здесь. Вам нужно сделать шаг назад и подумать о , какие параллельные алгоритмы могут дать тот же результат, что и ваш последовательный алгоритм .

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

Таким образом, по сути, превратите алгоритм "выталкивания" в алгоритм "вытягивания".

Это становится намного сложнее, если у вас действительно есть веская причина для отслеживания отдельных частиц, но у нас нетМне действительно было дано достаточно информации.

Мне также было любопытно, можно ли здесь использовать ROP (выходные блоки рендеринга), поскольку их функция выглядит довольно схожей с этим типом вычислений. Из некоторых источников кажется, что буфер рендеринга на графическом процессоре может быть оптимизирован, например, для доступа на запись.

Да, это определенно стоит изучить, если вы должны придерживаться подхода «push», так какпохоже, что аддитивное смешивание - это то, что вы хотите. В дополнение к операциям смешивания, трафаретный буфер также может представлять интерес. Возможно, вы захотите рассмотреть рендеринг «точечных спрайтов», которые поддерживаются всеми основными 3D-API - рендеринг отдельных пикселей - это не то, что обычно делают 3D-приложения, и, следовательно, не обязательно то, для чего оптимизированы графические процессоры и их драйверы, а точечные. спрайты в основном предназначены для рисования систем частиц.

...