Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие_CUDA.docx
Скачиваний:
5
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆
      1. Методические рекомендации

Объем глобальной памяти самый большой из всех типов памяти, но в то же время эта память – самая медлительная по техническим характеристикам: скорости считывания и записи.

Можно выделить два способа оптимизации в работе с глобальной памятью:

  • выравнивание размеров используемых типов;

  • использование объединенных запросов.

Поскольку обращение к глобальной памяти происходит через чтение/запись 32/64/128 битовых слов, крайне важным является то, что адрес, по которому происходит доступ, должен быть выровнен по размеру слова, т.е. кратен размеру слова в байтах.

Так, если происходит чтение 32 битого слова по адресу 0, то потребуется одно обращение к памяти. Если же чтение будет происходить с адреса 1, то потребуют­ся два обращения к памяти, каждое из которых будет выровнено. Первое читает по адресу 0, а второе по адресу 4 (рис. 3.15).

Рис. 3.15. Пример выровненного (сверху) и невыровненного (внизу) 4 байт блока

Выравнивание производится с помощью ключевого слова __align__(размер выравнивания).

Хотя все функции, выделяющие глобальную память, выделяют ее выровненной по 256 байтам, тем не менее проблемы с выравниванием могут возникать и в этом случае. Пусть у нас есть массив из следующих структур, выделенный в глобальной памяти:

struct vec3

{

float х, у, z;

};

Даже если каждый элемент массива (длиной в 12 байт) полностью помещается в 16 байтах, и адрес первого элемента массива выровнен по 16 байтам, то адрес следующего элемента уже не будет выровнен по 16 байтам, и его чтение потребует двух обращений. Поэтому если элементы этого массива читаются нитями, то каждое второе обращение к массиву будет осуществляться в два обращения, т.е. будет заметный проигрыш в скорости.

Проще всего это исправить, обеспечить выравнивание элементов массива, которое можно достигнуть следующим способом:

struct __align__ (16) vec3

{

float х, у, z;

};

Теперь все элементы массива будут находиться на адресах, кратных 16, что обеспечит чтение одного элемента за раз. Таким образом, хотя мы и увеличили объем выделяемой и читаемой памяти, но работа с этой памятью будет происходить заметно быстрее.

Больший прирост производительности можно получить при объединении большого количества запросов в глобальную память в один. Правильное использование этой возможности позволяет получить почти 16-кратное ускорение.

Все обращения мультипроцессора к памяти происходят независимо для каждой половины варпа. Поэтому максимальное объединение ­ – это когда все запросы одного полуварпа удается объединить в один большой запрос на чтение не­прерывного блока памяти. Для этого необходимо выполнение ряда условий, которые применяются независимо к каждой половине варпа.

Для того чтобы GPU произвел объединение запросов нитей полуварпа, необходимо, чтобы были выполнены следующие условия:

  • все нити обращаются к 32-­битовым словам, давая в результате один 64‑байтовый блок, или все нити обращаются к 64-­битовым словам, давая в результате один 128‑байтовый блок;

  • получившийся блок выровнен по своему размеру, т.е. адрес получающегося 64-байтового блока кратен 64, а адрес получающегося 128­-байтового блока кратен 128;

  • все 16 слов, к которым обращаются нити, лежат в пределах этого блока;

  • нити обращаются к словам последовательно – k-­я нить должна обращаться к k­-му слову (при этом допускается, что отдельные нити пропустят обращение к соответствующим словам).

  • Если нити полуварпа не удовлетворяют какому-либо из данных условий, то каждое обращение к памяти происходит как отдельная транзакция.

      1. Защита лабораторной работы

Защита лабораторной работы заключается в демонстрации работающей программы и сдаче печатного отчета, содержащего все необходимые разделы согласно требованиям данного методического пособия. Студент должен владеть теоретическими знаниями, свободно комментировать все строчки кода программы и уметь формулировать выводы о проделанной работе.

    1. Лабораторная работа № 5. Оптимизации приложений с использованием текстурной памяти

      1. Цель работы

Целью работы является закрепление знаний о работе с моделью памяти в технологии CUDA и изучение механизма оптимизации приложений с использованием текстурной памяти.

      1. Порядок выполнения работы

  1. Написать программу на графическом процессоре согласно индивидуальному варианту.

  2. Исходные данные в задаче необходимо располагать в текстуры (cudaArray текстурную память).

  3. Сравнить время выполнения алгоритмов (через глобальную, через разделяемую и через текстурную память)

      1. Теоретическая часть

Особенности константной памяти.

Константная память используется тогда, когда в ядро необходимо передать много различных данных, которые будут одинаково использоваться всеми потоками ядра.

Объявление глобальной переменной с именем contsData для использования в качестве константной памяти:

__constant__ float contsData [256];

Копирование данных с центрального процессора в константную память:

cudaMemcpyToSymbol (constData, hostData, sizeof (data), 0, cudaMemcpyHostToDevice);

Использование внутри ядра ничем не отличается от использования любой глобальной переменной на хосте.