
- •3.3 Расширение языка c……………………………………………………….46
- •1.1 Задача Дирихле
- •1.2 Метод простых итераций
- •1.3 Методы Якоби
- •1.4 Методы Зейделя и его модификации
- •2 Параллельные методы решения задачи Дирихле для систем с общей памятью
- •2.1 Использование OpenMp для организации параллелизма
- •2.2 Проблема синхронизации параллельных вычислений
- •2.3 Возможность неоднозначности вычислений в параллельных программах
- •2.4 Исключение неоднозначности вычислений
- •2.5 Волновые схемы параллельных вычислений
- •3 Параллельные вычисления с использованием видеокарты
- •3.1 Общие сведения о gpu и nvidia cuda
- •3.1.1 Разница между cpu и gpu в параллельных расчётах
- •3.1.2 Первые попытки применения расчётов на gpu
- •3.1.3 Возможности nvidia cuda
- •3.1.4 Области применения параллельных расчётов на gpu
- •3.2 Аппаратная и программная реализация cuda
- •3.2.1 Состав nvidia cuda
- •3.2.2 Архитектура gpu
- •3.2.3 Модель программирования cuda: потоковая модель
- •3.2.4 Модель программирования cuda: модель памяти
- •3.3 Расширение языка c
- •3.3.1 Директива вызова ядра
- •3.3.2 Основы cuda host api
- •3.3.3 Работа с памятью в cuda
- •3.3.4 Использование событий для синхронизации на cpu
- •3.3.5 Получение информации об имеющихся gpu и их возможностях
- •3.3.6 Компиляция
- •Http://habrahabr.Ru/blogs/cuda/54707/
3.1.2 Первые попытки применения расчётов на gpu
Идея использования графических процессоров для математических расчётов не нова. Первые попытки были сделаны ещё в 90-х годах прошлого века. Самые первые попытки такого применения были крайне примитивными и ограничивались использованием некоторых аппаратных функций, таких, как растеризация и Z-буферизация.
В 2003 году, с появлением эволюционировавших шейдеров, была достигнута новая планка - на этот раз выполнение матричных вычислений. Это был год, когда целая секция SIGGRAPH ("Computations on GPUs/Вычисления на GPU") была выделена под новую область информационных технологий. Эта ранняя инициатива получила название GPGPU (General-Purpose computation on GPU, универсальные вычисления на GPU). Наиболее известен BrookGPU — компилятор потокового языка программирования Brook, созданный для выполнения неграфических вычислений на GPU.
Чтобы понять роль BrookGPU, нужно разобраться, как всё происходило до его появления. Единственным способом получить ресурсы GPU в 2003 году было использование одного из двух графических API - Direct3D или OpenGL. Следовательно, разработчикам, которые хотели получить возможности GPU для своих вычислений, приходилось опираться на два упомянутых API. Проблема в том, что они не всегда являлись экспертами в программировании видеокарт, а это серьёзно осложняло доступ к технологиям. Если 3D-программисты оперируют шейдерами, текстурами и фрагментами, то специалисты в области параллельного программирования опираются на потоки, ядра, разбросы и т.д. Поэтому сначала нужно было привести аналогии между двумя мирами.
Поток (stream) представляет собой поток элементов одного типа, в GPU он может быть представлен текстурой. В принципе, в классическом программировании есть такой аналог, как массив.
Ядро (kernel) – функция, которая будет применяться независимо к каждому элементу потока; является эквивалентом пиксельного шейдера. В классическом программировании можно привести аналогию цикла - он применяется к большому числу элементов.
Чтобы считывать результаты применения ядра к потоку, должна быть создана текстура. На CPU эквивалента нет, поскольку там есть полный доступ к памяти.
Управление местоположением в памяти, куда будет производиться запись (в операциях разброса/scatter), осуществляется через вершинный шейдер, поскольку пиксельный шейдер не может изменять координаты обрабатываемого пикселя.
Как можно видеть, даже с учётом приведённых аналогий, задача не выглядит простой. И на помощь пришёл Brook. Под этим названием подразумеваются расширения к языку C ("C with streams", "C с потоками"), как назвали их разработчики в Стэнфорде. По своей сути, задача Brook сводилась к сокрытию от программиста всех составляющих 3D API, что позволяло представить GPU как сопроцессор для параллельных вычислений. Для этого компилятор Brook обрабатывал файл .br с кодом C++ и расширениями, после чего генерировал код C++, который привязывался к библиотеке с поддержкой разных выходов (DirectX, OpenGL ARB, OpenGL NV3x, x86).
Рис. 10 Работа компилятора Brook
У Brook есть несколько заслуг, первая из которых заключается в выводе GPGPU из тени, чтобы с этой технологией могли знакомиться и широкие массы.
Преимущество Brook заключалось в популяризации концепции GPGPU, он существенно упростил доступ к ресурсам GPU, что позволило всё большим пользователям осваивать новую модель программирования. С другой стороны, несмотря на все качества Brook, предстоял ещё долгий путь, прежде чем ресурсы GPU можно будет использовать для вычислений.
Одна из проблем связана с разными уровнями абстракции, а также, в частности, с чрезмерной дополнительной нагрузкой, создаваемой 3D API, которая может быть весьма ощутима. Но более серьёзной можно считать проблему совместимости, с которой разработчики Brook ничего не могли сделать. Между производителями GPU существует жёсткая конкуренция, поэтому они нередко оптимизируют свои драйверы. Если подобные оптимизации, по большей части, хороши для геймеров, они могут в один момент покончить с совместимостью Brook. Поэтому сложно представить использование этого API в промышленном коде, который будет где-то работать. И долгое время Brook оставался уделом исследователей-любителей и программистов.
Естественно, у Brook было множество недостатков, но даже просто его появление вызвало значительный прилив внимания тех же NVIDIA и ATI к инициативе вычислений на GPU, так как развитие этих возможностей серьёзно изменило рынок в дальнейшем, открыв целый новый его сектор — параллельные вычислители на основе видеочипов.
В дальнейшем, некоторые исследователи из проекта Brook влились в команду разработчиков NVIDIA, чтобы представить программно-аппаратную стратегию параллельных вычислений, открыв новую долю рынка. И главным преимуществом этой инициативы NVIDIA стало то, что разработчики отлично знают все возможности своих GPU до мелочей, и в использовании графического API нет необходимости, а работать с аппаратным обеспечением можно напрямую при помощи драйвера. Результатом усилий этой команды стала NVIDIA CUDA (Compute Unified Device Architecture) — новая программно-аппаратная архитектура для параллельных вычислений на NVIDIA GPU.