Вообще тип ![]()
является одним из добавленных в CUDA C типов.
Кроме него в этом языке появились и другие типы-векторы, например ![]()
, ![]()
, ![]()
, ![]()
, базирующиеся на стандартном типе ![]()
. Удобный для работы с двумерными
структурами, тип ![]()
активно использовался в этой
работе.
Кроме спецификаторов, некоторых
новых типов и директивы запуска ядра в CUDA C добавлен
также набор дополнительных функций. Так, для того чтобы функция-ядро
выполнялась над набором данных, необходимо выделить некоторое количество памяти
на GPU, и это
осуществляется при помощи аналога стандартной функции ![]()
- ![]()
. Чтение и запись в область памяти,
выделенную этой особой функцией, разрешается только из кода, выполняемого
устройством; разыменовывать указатель, возвращаемый ей, с центрального процессора
нельзя. Поэтому еще одним очевидным расширением языка должна стать специальная
функция, которая освобождает память устройства, аналог ![]()
. Она получила название ![]()
и вызывается из кода, выполняемого CPU. Функция ![]()
в свою очередь позволяет копировать
данные из памяти CPU в память GPU и обратно,
что является одним из основных способов обмена данными между процессором и
устройством. Подробнее синтаксис вызова и использование всех этих функций будут
рассмотрены в четвёртой главе.
Практически во всех программах,
которые выполняются многопоточно, в их параллельной части необходимо
осуществлять какие-то операции с номером текущего потока. В архитектуре CUDA номер
потока - это номер текущей нити, который можно получить, зная размер блока,
номер блока в сетке и номер нити в блоке. За эти параметры отвечают встроенные
переменные ![]()
, ![]()
и ![]()
соответственно.
Для примера рассмотрим задачу,
которая прекрасно накладывается на архитектуру параллельных вычислений. Найдем
приближённое значение интеграла:
применяя метод прямоугольников. Как
известно, точное значение такого интеграла равно числу ![]()
.
Простейший пример кода на C++ может выглядеть так:
Тот же код, преобразованный для работы с технологией CUDA:
) часть, выполняемая CPU:
) функция
выполняемая
на
GPU:
Результат работы программы:
Рассмотренный пример очень хорошо иллюстрирует использование CUDA, которое, как легко заметить, сводится к следующему алгоритму:
) выделение памяти на GPU;
) копирование данных из памяти CPU в выделенную память GPU;
) осуществление запуска ядра;
) копирование результатов вычислений обратно в память CPU;
) освобождение выделенной памяти GPU.
Фактически для каждого допустимого индекса входных массивов запускается отдельная нить для осуществления нужных вычислений. Все эти нити выполняются параллельно, и каждая нить может получить информацию о себе через встроенные переменные. /10, 13/
Что касается выигрыша во времени, то, согласно эксперименту, для одного миллиона разбиений интервала интегрирования время вычисления с помощью CUDA по сравнению с временем исполнения аналогичной CPU-программы сократилось более, чем в десять раз.
В современном мире области возможного применения технологии CUDA невероятно широки. Массивно-параллельные вычисления успешно используются в некоторых областях медицины, в обработке изображений, в науках об окружающей среде. В гидродинамике, например, очень сложное движение обтекающих потоков воздуха или жидкости сделало невероятно ресурсоёмким процесс конструирования рабочих механизмов, а с применением параллельного вычисления появилась возможность значительно сократить время, а значит и стоимость расчетов. /10/
В наше время значительная часть стоящих перед человечеством физических задач не может быть решена за обозримое время, если использовать для решения только параллельные алгоритмы. Поэтому в данной дипломной работе предлагается проверить возможности технологии CUDA в задачах математической физики. Для примера была взята задача о колебаниях, которая прекрасно накладывается на параллельную архитектуру.
2. МЕТОДЫ И МЕТОДИКИ ИССЛЕДОВАНИЙ
В процессе работы над поставленными задачами использовались следующие математические методы:
) для решения уравнения колебаний - метод разделения переменных;
) для расчёта входящих в решение коэффициентов - быстрое преобразование Фурье;
) для альтернативного расчета коэффициентов - метод квадратур Лежандра-Гаусса.
Также использовались следующие средства:
) для написания кода и компиляции - интегрированная среда разработки Microsoft Visual Studio 9.0;
) для создания кода, выполняемого GPU, и его компиляции - набор инструментов CUDA Toolkit 4.0 и комплекс средств разработки CUDA SDK 4.0;
) для пошаговой проверки результатов, для расчёта узлов и весовых коэффициентов метода квадратур Гаусса - математический пакет Maple 13;
) для вычисления коэффициентов Фурье - библиотека CUFFT;
) для оценки времени расчёта коэффициентов Фурье на процессоре - библиотека FFTW;
) для визуализации результата - открытая графическая библиотека OpenGL 4.2.
Видеокарта, на которой производились расчёты: NVIDIA
GeForce 9200M
GS.
3. ЗАДАЧА О МАЛЫХ КОЛЕБАНИЯХ
колебание задача коэффициент амплитуда
Для демонстрации возможностей параллельного вычисления в общем и технологии CUDA в частности была выбрана задача о малых колебаниях. Такой выбор основан на исключительной простоте задачи, что позволяет найти несколько разных алгоритмов вычисления и остановиться на оптимальном, а также с помощью дополнительных независимых расчётов легко проверить точность получаемого решения. Также задача о колебаниях хороша тем, что даёт прекрасную возможность для визуализации результата, что послужит лишним подтверждением корректности вычислений и наглядной демонстрацией их производительности.
На начальном этапе работы все расчёты производились на примере одномерной задачи о колебаниях струны. После достижения положительного результата они были распространены на случай двумерной мембраны. Именно этот двумерный случай впоследствии и был визуализирован.
.1 Постановка задачи. Вывод уравнения
Возьмём натянутую струну (под струной здесь и далее понимается тонкая упругая нить) и немного отклоним её от положения равновесия, а затем отпустим. Получив некоторое количество энергии струна начнёт колебательный процесс, который - в идеальном случае отсутствия сопротивления среды - будет продолжаться бесконечно долго.
В последующих рассуждениях остановимся именно на этом простейшем случае свободных поперечных колебаний и найдем уравнение, иллюстрирующее поставленную задачу.
Пусть есть струна, которая способна
совершать малые колебания в плоскости ![]()
около некоторого равновесного
положения, совпадающего, положим, с осью ![]()
. Пусть также существует некоторая
функция координаты и времени ![]()
, которая определена для всех точек
струны и несёт в себе смысл отклонения её в точке ![]()
в момент времени ![]()
от равновесного положения.
Допустим, что натяжение достаточно велико и можно пренебречь сопротивлением при
изгибе и силой тяжести. Вместе с этим будем опускать все величины высшего
порядка малости по сравнению с ![]()
Так как струна изгибу не
сопротивляется, сила её натяжения ![]()
в любой точке ![]()
будет направлена по касательной
этой точке /4/. В силу нашего приближения любой участок струны даже после
отклонения от равновесия своей длины не изменит. Действительно, длина плоской кривой,
заданной уравнением ![]()
, опирающейся на точки с
координатами![]()
и ![]()
, как известно, равна:
Рисунок 1
что, при учёте пренебрежения малым
слагаемым, даст ![]()
, то есть длину участка струны в
положении равновесия. Определяемое законом Гука абсолютное значение силы
натяжения ![]()
напрямую зависит от удлинения
струны, а значит в контексте данной задачи будет постоянным, не зависящим ни от
координаты, ни от времени, и равным некоторому значению ![]()
.
Согласно второму закону Ньютона,
сумма сил, приложенных к элементу струны ![]()
, равна произведению ускорения
такого элемента на его массу (рисунок 1). Массу выразим через линейную
плотность ![]()
, а сила натяжения, действующая на
участок струны, может быть представлена разностью:
![]()
Таким образом, уравнение движения в
проекции на ось, перпендикулярную оси![]()
, запишется так:
Теперь выразим синус угла через
производную смещения:
и получим: