Vitalik



Технология AMD Streamtm

Программирование на Brook+


Введение




    Язык Brook был первоначально разработан командой из Стэндфордского Университета для реализации потоковой вычислительной модели программирования. Brook+ является лишь модифицированной версией обычного Brook которая была разработана компанией AMD для обеспечения возможности потоковых вычислений на её оборудовании. На данный момент таким оборудованием являются графические процессоры, начиная с Radeon 2400 Pro, и профессиональные ускорители серии FireStream. Кроме того, по состоянию на 18 сентября 2008 года на сайте AMD, в отличии от основного конкурента в области GPU - компании NVidia, до сих пор не появилось финального релиза SDK. На момент написания данного материала на странице была доступен для скавания лишь SDK версии 1.2-beta. Более того библиотека ACML и вовсе находится на стадии альфа релиза и не доступна для широкого круга. По краней мере мне её после запроса по элктронной почте не выслали до сих пор. Но будем надеятся на лучшее. Возможно в скором времени мы увидим наконец-то первый финальный релиз. Ну а пока весь маериал будет основываться на бета-релизе.



    Системные требования


    Как уже было сказано во введении для работы с Brook+ потребуется видеокарта не ниже Radeon 2400 Pro. Поддерживаются операционные системы Microsoft Windows XP и Vista в 32-х и 64-х битных версиях. Для компиляции программ необходима среда разработки Microsoft Visual Studio 2005(версия 8). Кроме того поддерживается также операционная система Linux. Лично я использовал видеокарту Radeon 3450 с 512 Мб встроенной памяти DDR2 и компьтер со следующей конфигурацией - процессор Intel Pentium D 915 2.8 ГГц, 4 Гб оперативной памяти DDR2 667 Dual Channel, чипсет Intel 945G, 400 Гб жесткий диск, операционнная система Windows XP Professional 32 bit.


    Основы сиснтаксиса Brook+



    Потоковая модель программирования подразумаевает наличие потоков данных(streams) которые необходимо обрабатывать с помощью специальной функции. Такая функция в Brook+ называется ядром(kernel). Потоки данных являются ничем иным как массивами из элементов одинанокового типа данных. Brook+ поддерживаются следующие типы данных: int - 32-х битное целое float - 32-х битное вещественное double - 64-х битное вещественное Кроме того допускается использование структур. Для описания потоков используется комбинация символов <>. Например: int a<>; - одномерный поток(вектор) произвольной длины из целых чисел; int a<100>; - одномерный поток(вектор) из ста чисел; int a<100,100>; - двумерный поток(матрица) целых чисел размером 100х100; int a<100,100,100>; - трехмерный поток целых чисел размером 100х100; В настоящее время существуют ограничения на размер потоков. Официально поддерживаются двумерные потоки до 8192х8192 и одномерные до 223 элементов. На практике у меня возникла ошибка "Stack overflow" уже при использовании матрицы размером 300x300. Возможно это из-за нехватки мощности видеокарты или из-за испольвования бета-версии и не очень свежих драйверов. Будем надеятся что AMD с выходом новой версии программного обеспечения исправит это. Теперь разберемся с ядрами. Итак, ядро предназначено для проведения вычисления над потоками. Исходящие потоки маркируются словом out. Например следующее ядро суммирует 2 целочисленных вектора a и b и выводит результат в потоке c: kernel void sum(int a<>, int b<>, out float c<>) {       c = a + b; } Текущая версия Brook+ поддерживает до 128 потоков на входе и до 8 на выходе. К элементам потоков внутри ядра можно также обращаться по инедксу как в обычных массивах. Кроме того существуют также ядра отсечения(Reduction kernels) в которых можно применять условные операторы. Подробнее о них и многом другом написано в файле brookspec из прилагающейся документации. Настоятельно рекомендую с ней ознакомиться так там содержатся полные описания языковых синтаксических ограничений для ядер и не только.


    Пример кода на Brook+

    Ну а теперь перейдем к рассмотрению примера программы на Brook+. Нижеописанный пример суумирует два потока вещественных чисел a и b и выводит результат в потоке c. Рекомендую скачать данный пример sum.br на жесткий диск так как он может понадобится в следующей главе, которая является подробным руководством по запуску и компиляции Brook+ программ. Итак, исходный код sum.br выглядит следующим образом:




      #include "stdio.h"

      kernel void sum(float a<>, float b<>, out float c<>)

            {

                  c = a + b;

            }

      int main(int argc, char** argv)

            {

                  int i, j;

                  float a<10, 10>;

                  float b<10, 10>;

                  float c<10, 10>;

                  float input_a[10][10];

                  float input_b[10][10];

                  float input_c[10][10];

                  for(i=0; i<10; i++)

                        {

                              for(j=0; j<10; j++)

                                    {

                                          input_a[i][j] = (float) i;

                                          input_b[i][j] = (float) j;

                                    }

                        }

                  streamRead(a, input_a);

                  streamRead(b, input_a);

                  sum(a, b, c);

                  streamWrite(c, input_c);

                  for(i=0; i<10; i++)

                        {

                              for(j=0; j<10; j++)

                                    {

                                          printf("%6.2f", input_c[i][j]);

                                    }

                              printf("\n");

                        }

                  return 0;

            }




    Как видно из примера потоки a, b, c являются матрицами из элементов типа float размером 10х10 элементов. Обратите внимание, что в функции main, в отличии от ядра, указывается размерность потоков. Кроме того, видно, что птоки заполняются не напрямую, а сначала создаются и заполняются обычные матрицы input_a, input_b, input_c, а затем для загрузки данных в потоки a, b и c используются функции streamRead(для входящих потоков a и b) и StreamWrite(для исходящего потока c). В результате выполнения кода программы каждый элемент матрицы а будет просуммирован c соответствущим по индексу элементом матрицы b, а результат будет записан в соответствующую позицию матрицы c, после чего результат будет выведен на экран. Однако, как же откомпилировать данную программу? Для этого можно использовать интегрированную среду разработки Microsoft Visual Studio 2005. Следующий раздел посвящен тому, как это удобнее всего сделать.


    Brook+ в Visual Studio 2005

    Итак, перейдем к рассмотрению процесса компиляции Brook+ программ с помощью Visual Studio 2005. Надеюсь что к этому моменту на вашем компьютере уже утановлены AMD Stream SDK и сама Visual Studio 2005 и вы уже скачали исходный код примера sum.br. Для начала зайдем в папку где находятся примеры программ Brook+ которая по умолчанию находится в C:\Program Files\AMD\AMD BROOK 1.2_beta\samples. Как видно ниже на рисунке она имеет в своем составе папки apps и bin.





    Папка apps содержит исходные коды различных примеров, а в папке bin хранятся откомпилированные из этих исходных кодов программы. После каждой компиляции исполняемые файлы проекта записываются именно в папку bin так как таковы настройки проектов примеров , входящих в состав AMD Stream SDK. Если вы не специалист по параметрам проекта то рекомендую писать ваши приложения на базе готовых примеров, как это будет показано ниже. Итак приступим. Откроем первый пример binary_search из папки apps.



    Для открытия дважды щелкаем по файлу binary_serach.vcproj. Далее открываем в Solution Explorer'е открываем файл binary_serch.br как это показано на рисунке ниже.





    Теперь заменяем исходный код на код нашего примера.



    Затем запускаем с помощью кноки "Run". Если после запуска на экране появилось(промелькнуло) такое же окно как на рисунке ниже то наша программа Brook+ успешно откомпилировалась.





    Исполняемый находится в папке bin\xp_x86_32(при условии использования системы Windows XP 32-bit) под именем binary_search_d.exe.



    Обратите внимание, что в результате выполнения сначала был динамически сгенерирован файл binary_search.cpp, и только после этого из этого сгенерированного файла был получен исполняемый файл binary_search_d.exe. Такова особенность всех проектов Brook+. Однако если вам понадобится использовать код в каком-либо своем приложении, то для интеграции необходимо использовать код именно из cpp файла. Кроме того, исполняемые файлы требуют для запуска наличие уже установленного AMD Stream SDK, так в него входят необходимые для запуска библиотеки. Исходный код и запускной файл рассмотренного примера содержит архив который можно скачать здесь - sum.zip .

asd
Hosted by uCoz