Pull to refresh

AMD Brook+: с места в карьер

Computer hardware
Про nVidia CUDA хабровчане уже наслышаны, теперь настал черед и AMD Brook+. Brook+ позволяет вам писать программы на С и запускать их на видеокартах AMD (ну и как опция — автоматически можно сгенерировать CPU версию со средним качеством кода). Достижимая производительность — порядка 600млрд операций на AMD 4870.

NB: Статья — краткое введение, не стоит ожидать освещения тут всех аспектов программирования на Brook+ :-)

О железе


Brook+ работает начиная с карт HD2xxx (с ограничениями), по нормальному начинает работать с 3xxx-й серии. Если в рекламе вы видите что у 4870 800 процессоров, то на самом деле их 160, каждый из которых делает 5 инструкций за такт (у 3-й серии были серьёзные ограничения на одновременно выполняемые инструкции, у 4-й можно почти любые). В отличии от CUDA, где все достаточно «низкоуровневое», с Brook+ за вас все делает компилятор, все везде само кешируется, и перестает работать быстро в самый неподходящий момент. Из плюсов — доступ в память карты у AMD кешируется, а у nVidia нет.

С чего начать?


Как обычно, начать лучше с работающего примера SDK (рассказывать буду на примере Visual Studio 2005, Linux также поддерживается). Скачать SDK можно тут: http://ati.amd.com/technology/streamcomputing/sdkdwnld.html. Открываем samples.sln, начать можно с проекта hello_brook.
Обратите внимание на Custom Build Rule для файла hello_brook.br — оно генерирует .h и .cpp файлы которые вам нужно использовать в проекте:
mkdir brookgenfiles | "$(BROOKROOT)\sdk\bin\brcc_d.exe" -o "$(ProjectDir)\brookgenfiles\$(InputName)" "$(InputPath)"

Т.к. препроцессор не поддерживается, его можно вызывать отдельно самим, может получится примерно так:
cl /P /C file.br
copy file.i file_pp.br
"$(BROOKROOT)\sdk\bin\brcc_d.exe" -k -p cal file_pp.br

В последней строчке -p cal означает что генерируется только GPU ядро, CPU часть будет опущена (она может долго компилироваться, и не всегда нужна).

Структура программы


kernel void your_kernel(float input<>, out float output<>, float val)
{
if (input > val)
{
output = 1.0f;
}
else
{
output = 0.0f;
}
}


Вызывается примерно так:

unsigned int dim[] = {800*100};
::brook::Stream inputStream(1, dim);
::brook::Stream outputStream(1, dim);

inputStream.read(_input);
your_kernel(inputStream, outputStream, 123.35);
outputStream.write(_output);

Стоит обратить внимание, что в отличии от CUDA мы сразу задаем данные для каждого потока. Вот собственно и все :-) При работе помните, что пока массивы и структуры в .br файлах как следует не поддерживаются :-) Также нужно не забывать определять переменные в только начале тела функции, это вам не С++ :-)

Brook+ поддерживает и другие варианты запуска: когда исходые данные беруться из общего массива, когда определяются «координаты» потока (как в CUDA), аккумулирующие ядра (т.е. можно считать например сумму всех чисел массива). Об этом всем можно почитать в документации или в примерах SDK.

Оптимизация


Методы оптимизации в целом совпадают с CUDA:
  • Как можно меньше ветвлений в коде, где разные потоки идут по разным путям. Такой код не выполняется параллельно.
  • Т.к. каждый процессор суперскалярный, нужно позаботиться о том, чтобы у вас в коде всегда было минимум 5 независимых инструкций. Проще всего этого добиться развернув цикл руками в 5 раз (надеюсь в будущем это можно будет делать по #pragma unroll(5))
  • Используйте как можно меньше памяти. Чем меньше памяти вы используете, тем спокойнее будет кешу :-)


Не получается?


В первую очередь следует прочитать документацию вместе с SDK в папке Brook+_Documentation. Затем можно спросить на официальном форуме — к сожалению там разработчики не так часто отписываются. По-русски можно спросить у меня на форуме например, где отвечу я :-) Также много людей обитает на gpgpu.ru.

Заключение


Подытожим: Brook+ позволяет добиться феноменальной производительности на хорошо распараллеливающихся задачах, не требующих большого объема памяти, ценой дополнительных усилий по программированию в не очень удобной среде :-).

Надеюсь это введение поможет людям разобраться с программированием на Brook+. Если есть проблемы/вопросы — буду рад помочь. Ну а впереди нас ждет введение в OpenCL и SIMD x86
Tags:
Hubs:
Total votes 32: ↑29 and ↓3 +26
Views 1.5K
Comments Comments 14