стр. 1 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Лабораторная работа №1 “Обработка одномерных массивов и матриц при помощи CUDA” Цель работы: научиться использовать современную параллельного программирования CUDA для обработки массивов и матриц. технологию одномерных Теоретическая часть В разработке. Для выполнения данной работы можно пользоваться источником Сандерс Дж., Кендрот Э. “Технология CUDA в примерах”, гл. 1 – 4, стр. 16 – 58. Задание и порядок выполнения лабораторной работы Часть 1. Установка требуемого программного обеспечения 1.1 Установка MS Visual Studio Для работы с технологией CUDA потребуется MS Visual Studio. Самую последнюю версию среды лучше не использовать, так как существует вероятность того, что последний комплект ПО CUDA ее еще не поддерживает. На момент написания этих методических указаний студентам лучше использовать Visual Studio 2005 – Visual Studio 2012. Заметим попутно, что для учебных целей нет разницы в использовании Professional или Express версии Visual Studio. Для работы с CUDA необходимо, чтобы среда поддерживала компиляцию программ на языке С/С++. Поэтому, если Вы устанавливаете Professional версию, проблем, как правило, не бывает. При установке Express версии нужно обращать внимание на поддерживаемый язык и тип Вашей операционной системы (32 или 64 разряда). Express версию можно скачать бесплатно с сайта Microsoft по ссылке: [http://www.visualstudio.com/downloads/download-visual-studio-vs] 1.2 Установка CUDA Developer Drivers, CUDA Toolkit, GPU Computing SDK После установки MS Visual Studio необходимо установить CUDA Developer Drivers, CUDA Toolkit, GPU Computing SDK. Технология CUDA была разработана компанией NVIDIA для ускорения вычислений при обработке графики за счет параллельной обработки данных. Принято считать, что указанная технология поддерживается во всех видеокартах NVIDIA, выпущенных после 2007 года. Поэтому если у Вас именно такая видеокарта – Вы сможете почувствовать настоящую мощь параллельных вычислений. Окончательно убедиться в том, что Ваша видеокарта поддерживает технологию CUDA можно на сайте производителя. стр. 2 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Однако если у Вас нет подходящего оборудования, изучить указанную технологию и научиться писать программы для CUDA все равно можно. Правда “почувствовать мощь” уже не получится. Этапы дальнейшей установки будут несколько отличаться для конфигурации с установленной на машине видеокартой от NVIDIA и без нее. ►Для конфигурации ПК с видеокартой от NVIDIA нужно зайти на страницу загрузки программного обеспечения для CUDA, [https://developer.nvidia.com/cuda-toolkit-archive] перейти с нее на страницу с последней версией (на момент написания это версия 6.5), скачать и установить на свой компьютер. Начиная с версии 5.0 все три пакета, которые необходимы для программирования под CUDA, – CUDA Developer Drivers, CUDA Toolkit, GPU Computing SDK – объединены в один инсталлятор, что, конечно же, очень удобно. При загрузке обращайте внимание на версию и тип Вашей операционной системы. При установке не используйте длинных путей, содержащих русские буквы, а по возможности короткие пути. Это пригодится впоследствии при интеграции этих пакетов в Visual Studio. ►Для конфигурации ПК без видеокарты от NVIDIA нужно зайти на страницу загрузки программного обеспечения для CUDA, [https://developer.nvidia.com/cuda-toolkit-archive] перейти с нее на страницу с версией 2.3, скачать и установить CUDA Toolkit, GPU Computing SDK. В отличие от первого варианта конфигурации, пакет CUDA Developer Drivers не нужен, так как у Вас нет соответствующего оборудования. Собственно, он даже не установится. При скачивании пакетов обращайте также внимание на версию и тип Вашей операционной системы. При установке CUDA Toolkit, GPU Computing SDK постарайтесь использовать короткие пути без русских букв. Это пригодится впоследствии при интеграции этих пакетов в Visual Studio. Наиболее оптимальный вариант – использовать следующие пути установки: [С:\CUDA\TOOLKIT], [С:\CUDA\SDK]. Почему необходимо устанавливать ПО CUDA именно версии 2.3? Дело в том, что именно данная версия – последняя в линейке ПО CUDA, в которой есть поддержка режима эмуляции. Следовательно, если включить данный режим в настройках проекта (об этом речь далее), то компилировать и исполнять программный код CUDA можно и без реального устройства, поддерживающего технологию CUDA. Не стоит также устанавливать CUDA Toolkit, GPU Computing SDK разных версий. Они могут оказаться несовместимы друг с другом. стр. 3 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 После этого в Visual Studio потребуется указать пути к директориям CUDA Toolkit, в которых хранятся основные заголовочные файлы, исполняемые файлы и библиотеки. Для этого следует открыть окно с настройками параметров (“Сервис” – “Параметры”), а во вкладке “Проекты и решения” выбрать пункт “Каталоги VC++”. В качестве платформы по умолчанию следует выбрать “Win32” или “Win64” в зависимости от разрядности ОС, в поле “Показать каталоги для” выбрать “Исполняемые файлы”, как показано на рис. 1. Рис. 1. – Настройка путей к CUDA Toolkit Далее по нажатию кнопки нужно создать новую строку и вписать путь к папке, в которой хранятся исполняемые файлы CUDA Toolkit. Как правило, эти файлы находятся в папке bin, которая, в свою очередь, была создана при установке CUDA Toolkit. Таким образом, полный путь, который следует указать в настройках Visual Studio, выглядит так: [C:\CUDA\TOOLKIT\bin]. Далее следует проверить существование указанного пути, нажав кнопку . Если введенный путь некорректен, появится окно с сообщением об ошибке; если же все пути из указанного списка исполняемых файлов существуют, ничего не произойдет. Не стоит пренебрегать этой проверкой: можно быть полностью уверенным, что путь указан корректно (хотя на самом деле это не так) и потратить много времени в поисках ошибок компиляции или отсутствующих библиотек в будущем. Аналогично необходимо указать пути к заголовочным файлам и библиотекам CUDA Toolkit. При этом в поле “Показать каталоги для” следует выбирать “Включаемые файлы” и “Файлы библиотек”. Все заголовочные файлы библиотеки CUDA Toolkit находятся в папке include, все библиотеки – в папке lib соответственно. После указания путей к заголовочным файлам и библиотекам не забывайте проверять их корректность, каждый раз нажимая на кнопку . стр. 4 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Часть 2. Создание и настройка первого проекта для CUDA Материал, описываемый в данной части, показывает, как создать проект, настроить интеграцию установленного ранее программного обеспечения, скомпилировать и запустить первое приложение для работы с CUDA. Обратите внимание – при создании нового проекта настройка должна выполняться каждый раз заново, поэтому, скорей всего, Вам придется возвращаться к данной части повторно. Для начала создадим новое консольное приложение Win32 С++. В настройках создания отметим опцию “Пустой проект”. При создании проекта не используйте папку для проектов по умолчанию, а старайтесь использовать короткие пути без русских букв. Автор этих методических указаний потратил несколько дней, пытаясь понять, откуда берутся ошибки даже при компиляции пустого проекта CUDA. Как оказалось впоследствии, проект нужно было перенести в папку с короткими путями. Наиболее оптимальный вариант – создать папку [С:\CUDA\PROJECTS] и создавать все проекты в ней. Попутно отметим, что данное правило создания проектов актуально для версии CUDA ToolKit версии 2.3. Возможно в последующих версиях (а сейчас уже вышла 6.5) данный недостаток был исправлен. Рис. 2. – Создание нового проекта CUDA (1 шаг) стр. 5 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Рис. 3. – Создание нового проекта CUDA (2 шаг) После создания нового проекта Вам следует проверить, добавились ли правила сборки в Visual Studio. В последних версиях CUDA Toolkit это выполняется автоматически. Правила сборки могут не добавляться в старых версиях CUDA Toolkit. Кроме того, правила сборки не будут добавлены, если Вы, например, установите сначала CUDA Toolkit, а только потом Visual Studio – в этом случае их просто еще некуда добавлять. Проверить добавились ли правила сборки можно через контекстное меню проекта. Рис. 4. – Вызов диалога Пользовательские правила построения Рис. 5. – Диалог “Пользовательские правила построения” стр. 6 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 В диалоге “Пользовательские правила построения” в названиях правил ищите строку “CUDA”. Таких правил может быть несколько, а их полные названия могут отличаться в зависимости от версии CUDA Toolkit. Автору встречались варианты “CUDA C/C++”, “CUDA Driver API”, “CUDA Runtime API” и т.д. Если подобных правил в указанном диалоге нет (как получилось, например, на рис. 5), Вам потребуется добавить их самостоятельно. Для этого в папке с установленным пакетом CUDA Toolkit поищите файл с названием [Cuda.Rules]. Если такого файла нет, попробуйте поискать его в папке с установленным пакетом GPU Computing SDK (в старых версиях файл Cuda.Rules может находиться в нем). Таких файлов Вы можете найти несколько, в разных поддиректориях. Добавьте все найденные правила вручную при помощи кнопки “Найти существующий”. В результате диалоговое окно примет вид, показанный на рис. 6. Рис. 6. – Диалог “Пользовательские правила построения” с добавленным правилом сборки для CUDA-программ Для того чтобы задействовать правила сборки в Вашем проекте, необходимо отметить флажок слева от названия правила и нажать кнопку “ОК”. Если же у Вас имеется несколько правил (в старших версиях CUDA Toolkit, например, есть разделение на CUDA Runtime API и CUDA Driver API), следует выбирать CUDA Runtime API. Именно CUDA Runtime API предоставляет интерфейс для более простых программ CUDA, в то время как CUDA Driver API более сложен в освоении, но вместе с тем дает доступ к низкоуровневому программированию для CUDA. Для начинающих он не нужен, и в данном цикле лабораторных работ не рассматривается. На следующем этапе нужно создать новый файл с исходным кодом в проекте. Для этого следует воспользоваться пунктом “Создать элемент” из контекстного меню проекта (см. рис. 7). Далее нужно выбрать файл типа С++. Имя файла может быть любым, но расширение файла обязательно стр. 7 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 следует задавать вручную, как показано на рис. 8. Традиционно файлы исходного кода CUDA имеют расширение *.cu. Если Вы не зададите расширение самостоятельно, указанный файл будет обычным *.cpp файлом, и добавленные ранее правила для него станут неприменимы. Из рисунка 6 можно понять, что именно по расширению файла Visual Studio определяет, какие правила для него нужно задействовать и как его компилировать. Рис. 7. – Создание нового файла с исходным кодом (шаг 1) Рис. 8. – Создание нового файла с исходным кодом (шаг 2) После создания файла следует убедиться в том, что к нему применились правила CUDA. Для этого нужно открыть свойства файла (не проекта!) и убедиться в том, что в поле “Инструмент” вкладки “Общие” задействуется именно подключенные ранее правила сборки CUDA (см. рис. 9 – рис. 10). Если по каким-либо причинам в поле инструмент окажется другой инструмент – можно переназначить инструмент вручную, выбрав его из списка. стр. 8 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Рис. 9. – Проверка соответствия исходного файла правилам CUDA (шаг 1) Рис. 10. – Проверка соответствия исходного файла правилам CUDA (шаг 1) Далее следует настроить пути для поиска средой Visual Studio компилятора CUDA программ, библиотек CUDA, заголовочных файлов и других исполняемых файлов (которые входят в состав CUDA ToolKit). Понадобится выполнить несколько настроек в свойствах проекта: - во-первых, нужно указать месторасположение библиотек CUDA во вкладке “Компоновщик – Общие – Дополнительные каталоги библиотек”, как показано на рис. 11. Здесь следует указать путь к папке, в которой хранятся библиотеки CUDA (файлы *.lib). Эта папка входит в состав CUDA ToolKit. Если таких папок в Вашей версии CUDA ToolKit несколько, то, нужно выбрать ту из них, которая соответствует типу Вашей операционной системы и выбранной версии CUDA API. Например, если файлы *.lib находятся в папке “runtime/lib/win32/*.lib” и у Вас 32 разрядная версия Windows, то выбирать нужно именно эту папку (помня о том, что в цикле лабораторных работ используется Runtime CUDA API). стр. 9 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 - во-вторых, следует указать библиотеку “cudart.lib” на вкладке “Компоновщик – Общие – Ввод”. Здесь можно ограничиться одним именем файла, без указания пути (см. рис. 12). Рис. 11. – Подключение библиотек CUDA Рис. 12. – Подключение cudart.lib Наконец, для студентов, у которых нет реальной видеокарты от NVidia, поддерживающей CUDA, необходимо включить режим эмуляции CUDA устройства. Обратите внимание на следующий любопытный факт: стр. 10 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 если режим эмуляции не включен, то программа компилируется и даже работает, только участки кода, которые должны исполняться на устройстве CUDA, просто игнорируются, хотя по идее должна возникать ошибка компиляции. Поэтому будьте внимательны и всегда включайте режим эмуляции, иначе результат выполнения Вашей программы будет не таким, как Вы ожидаете. Для того чтобы включить режим эмуляции в свойствах проекта зайдите во вкладку “CUDA Build Rule v2.3.0 – General – Emulation Mode” и выберите “Да” напротив соответствующего свойства (см. рис. 13). Рис. 13. – Включение режима эмуляции (для CUDA ToolKit v2.3.0) Теперь стоит проверить, как компилируется простейшее приложение CUDA. Откройте созданный ранее файл исходного кода и введите в него следующий фрагмент: #include <stdio.h> __global__ void add(int a, int b, int *c) { *c = a + b; } int main(void) { int c = 0; int *dev_c; cudaMalloc ((void**)&dev_c, sizeof(int)); add<<<1,1>>>(2, -1, dev_c); cudaMemcpy (&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost); printf("%d", c); system("pause"); return 0; } стр. 11 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 Нетрудно догадаться (несмотря на местами незнакомый синтаксис), что делает этот фрагмент кода: складывает 2 числа, -1 и 2, и выводит результат на экран. Но происходит это уже на CUDA устройстве. Поэтому если в результате Вы увидите 1, значит, Вы все сделали правильно. Если в результате будет 0, то, скорей всего, Вы забыли включить режим эмуляции. Могут также возникнуть и ошибки компиляции. В этом случае попробуйте скомпилировать такой код: int main(void) { return 0; } Если и в этом случае будут возникать ошибки компиляции, то можно проверить следующее: - если возникают ошибки вида “newline в константе”, то эта ошибка, скорей всего, связана с тем, что в пути к проекту или в пути к библиотекам имеются русские буквы; - если возникают ошибки вида “неразрешенная ссылка” – проверьте еще раз правильность указания путей ко всем библиотекам. - наконец, при компиляции проектов Ваш антивирус может “ругаться”. Просто добавьте компилятор nvcc.exe в список разрешенных приложений. Уж в нем-то вируса точно нет, при условии, что Вы скачали CUDA Toolkit с официального сайта NVidia. Часть 3. Изучение синтаксиса языка CUDA C После создания первого проекта CUDA следует более глубоко познакомиться с синтаксисом языка CUDA. Данный материал выходит за рамки практической части, поэтому его лучше изучать по теоретическому материалу, прилагаемому к данной работе, конспекту лекций или по дополнительным источникам. Одним из лучших источников сегодня является работа авторов Сандерс Дж., Кендрот Э. “Технология CUDA в примерах”. Здесь отметим лишь, что язык CUDA С очень сильно похож на обычный С, поэтому многие элементы синтаксиса окажутся Вам знакомы. Исключение составят лишь дополнительные функции и конструкции языка. Часть 4. Задание После ознакомления с синтаксисом языка, следует разработать программу на языке CUDA С в соответствии с вариантами заданий к лабораторной работе, приведенным в таблице 1. Все задания подобраны таким образом, чтобы ощущался эффект от использования CUDA технологии, в первую очередь, это, конечно же, время выполнения программы. Но и для студентов, не имеющих реального оборудования, выполнение программы не должно превращаться в мучительное ожидание. В стр. 12 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 результате объем вычислительной работы выбирался так, чтобы достигалась “золотая середина”. Во всех заданиях требуется создать матрицу (вектор) или несколько матриц (векторов) одинаковой размерности, указанной в таблице 1, заполнить их считанными из текстового файла значениями. Текстовые файлы следует предварительно подготовить, заполнив их случайными числами. Затем реализовать задание, используя обработку данных на CUDA. В конце вывести результаты вычислений опять в текстовый файл. Интерфейс программы – консольное приложение. В самом начале программа спрашивает имя входного и выходного файлов. Затем, после выполнения всех вычислений, печатает общее время работы (в секундах) на экране в виде дробного числа. Для измерения времени работы кода см. функции GetTickCount(), clock(). Общий принцип таков: засекаем время до начала вычислений, засекаем после, отнимаем от второго первое, печатаем результат. Содержание отчета: - титульный лист; - задание; - код программы; - экранная форма разработанного приложения; - выводы. Варианты заданий Таблица 1. Описание заданий № 1 2 3 4 5 6 7 8 9 Размерность массива или матрицы 217x217 216x216 215x215 217x217 211x211 216x216 215x215 217x217 216x216 10 215x215 11 12 234 233 Тип данны х цел. вещ. цел. вещ. цел. вещ. цел. вещ. цел. Описание задания Вычислить матрицу C = ½*A+B Вычислить матрицу C = (A+B)*5+8 Вычислить матрицу C = (B–A)* ½–8 Вычислить матрицу С = A*5 – B*8 + 3 Вычислить произведение матриц C = A*B Вычислить транспонированную матрицу C = AT Проверить, является ли матрица A диагональной Проверить, является ли матрица A единичной Проверить, является ли матрица A нулевой Проверить, что все числа в матрице меньше числа k, вещ. которое задает пользователь цел. Вычислить одномерный массив C = (A–B)*4+5 вещ. Вычислить одномерный массив C = (A+B)*6–10 стр. 13 (С) Павлий В.А., кафедра КСМ, ДонНТУ, 2014 13 14 15 16 232 231 230 234 цел. вещ. цел. вещ. 17 233 цел. 18 19 232 231 вещ. цел. 20 230 вещ. 21 22 23 24 25 26 27 28 29 216x216 215x215 214x214 216x216 210x210 215x215 214x214 216x216 215x215 вещ. цел. вещ. цел. вещ. цел. вещ. цел. вещ. 30 214x214 цел. 31 32 33 34 35 36 233 232 231 230 229 233 вещ. цел. вещ. цел. вещ. цел. 37 232 вещ. 38 39 231 230 цел. вещ. 40 229 цел. Вычислить одномерный массив C = (B–A)*½–8 Вычислить одномерный массив C = A*3–B+3 Вычислить одномерный массив C = B+3*A–8 Вычислить отраженный относительно середины массив C Поменять в одномерном массиве элементы, находящиеся на четных и нечетных местах Проверить, является ли одномерный массив единичным Проверить, является ли одномерный массив нулевым Проверить, что все числа в одномерном векторе меньше числа k, которое задает пользователь Вычислить матрицу C = ½*A+B Вычислить матрицу C = (A+B)*5+8 Вычислить матрицу C = (B–A)* ½–8 Вычислить матрицу С = A*5 – B*8 + 3 Вычислить произведение матриц C = A*B Вычислить транспонированную матрицу C = AT Проверить, является ли матрица A диагональной Проверить, является ли матрица A единичной Проверить, является ли матрица A нулевой Проверить, что все числа в матрице меньше числа k, которое задает пользователь Вычислить одномерный массив C = (A–B)*4+5 Вычислить одномерный массив C = (A+B)*6–10 Вычислить одномерный массив C = (B–A)*½–8 Вычислить одномерный массив C = A*3–B+3 Вычислить одномерный массив C = B+3*A–8 Вычислить отраженный относительно середины массив C Поменять в одномерном массиве элементы, находящиеся на четных и нечетных местах Проверить, является ли одномерный массив единичным Проверить, является ли одномерный массив нулевым Проверить, что все числа в одномерном векторе меньше числа k, которое задает пользователь