Программирование графических процессоров Лабораторная 2
Состав работы
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Работа представляет собой rar архив с файлами (распаковать онлайн), которые открываются в программах:
- Microsoft Word
Описание
Задание
1. Прочитайте главу из теоретического материала "Разделяемая память" и ответьте на контрольные вопросы (ответы на контрольные вопросы не нужно включать в отчёт по лабораторной работе).
2. Оптимизируйте алгоритмы, реализованные в лабораторной работе №1 при помощи разделяемой памяти.
3. Постройте графики зависимости времени выполнения алгоритма от размера матрицы и вектора (Размеры матрицы 1000x500, 1000x1000, 1500x1000, 2000x1000, 2000x1500, 2500x1500, 2500x2000).
4. Проанализируйте, реализованные алгоритмы при помощи утилиты nvprof на эффективность доступа к глобальной памяти.
Методические указания по выполнению лабораторной работы
Разделяемая память – это своего рода кэш. Ускорения от использования разделяемой памяти можно достичь только если к каким-то данным происходит многократное обращение. Тогда переместив их в разделяемую память из глобальной можно сократить время затраченное на обращение в память за счёт высокой скорости разделяемой памяти.
Рассмотрим схему параллельного умножения матрицы на вектор.
Рис. 1 – схема умножения матрицы на вектор
Каждая нить берёт по одной строке матрицы и умножает попарно элементы строки на элементы вектора. Все нити используют один и тот же вектор. Скопировав вектор в разделяемую память можно получить ускорения выполнения алгоритма. Но проблема разделяемой памяти в том, что её объём очень мал по сравнению с объёмом глобальной памяти. Поэтому нужно предусмотреть ситуацию когда вектор полностью в память не помещается.
Учитывая, что разделяемой памяти может не хватить нужно модифицировать алгоритм таким образом чтобы часть вектора копировалась в разделяемую память. Нити умножали часть строки на часть вектора, расположенного в разделяемой памяти. Затем копировали следующую часть вектора в разделяемую память и умножали элементы следующей части строки и т.д. как показано на рисунке 2.
Рис. 2 – умножение нитью строки на вектор с копированием частей вектора в разделяемую память
Копирование частей вектора можно производить параллельно, каждая нить может копировать в разделяемую память один или несколько элементов. Таким образом псевдокод алгоритма будет выглядеть следующим образом:
//Выделяем разделяемую память
//Количество элементов будет равно количеству нитей в блоке.
__shared__ shared_vector[THREAD_PER_BLOCK];
//k - номер части вектора. +1 потому что M не обязательно делится нацело
for(k = 0; k < (M / THREAD_PER_BLOCK) + 1; ++k) {
//p - реальный номер элемента вектора
//который будет скопирован нитью в разделяемую память
p = threadIdx.x + THREAD_PER_BLOCK * k;
//Проверка на выход за пределы вектора
if(p < M) {
//Копирование из глобальной памяти в разделяемую
//Т.к. размер разделяемой памяти равен размеру блока
//Каждая нить может скопировать по одному элементу
shared_vector[threadIdx.x] = V[threadIdx.x + THREAD_PER_BLOCK * k];
}
//Синхронизация. Нужно дождаться пока все нити скопируют свои элементы
//Потому что каждая нить использует скопированную часть вектора полностью
__syncthread();
//i - глобальный номер нити, N - количество строк в матрице
//Проверка не выходим ли за границы матрицы
if (i < N) {
//Умножение части вектора на часть строки
//j - порядковый номер элемента в части вектора или строки матрицы
//чтобы получить реальный номер элемента матрицы
//нужно прибавить j количеству полностью обработанных элементов
for(j = 0; j < THREAD_PER_BLOCK; ++j) {
C[i] += A[i][j + k * THREAD_PER_BLOCK] * shared_vector[j];
}
}
//Синхронизация нужна для того чтобы убедиться
//что все нити закончили работу с частью вектора
//потому что следующая операция - перезапись разделяемой памяти
__syncthread();
}
В данном коде можно сделать ещё одну оптимизацию – перенести операции над вектором C в разделяемую память. И скопировать результат в глобальную только после того как результат будет посчитан. С учётом этого алгоритм будет выглядеть следующим образом:
//Выделяем разделяемую память
//Количество элементов будет равно количеству нитей в блоке.
__shared__ shared_vector[THREAD_PER_BLOCK];
__shared__ shared_c[THREAD_PER_BLOCK];
shared_c[threadId.x] = 0;
__syncthread();
//k - номер части вектора. +1 потому что M не обязательно делится нацело
for(k = 0; k < (M / THREAD_PER_BLOCK) + 1; ++k) {
//p - реальный номер элемента вектора
//который будет скопирован нитью в разделяемую память
p = threadIdx.x + THREAD_PER_BLOCK * k;
//Проверка на выход за пределы вектора
if(p < M) {
//Копирование из глобальной памяти в разделяемую
//Т.к. размер разделяемой памяти равен размеру блока
//Каждая нить может скопировать по одному элементу
shared_vector[threadIdx.x] = V[threadIdx.x + THREAD_PER_BLOCK * k];
}
//Синхронизация. Нужно дождаться пока все нити скопируют свои элементы
//Потому что каждая нить использует скопированную часть вектора полностью
__syncthread();
//i - глобальный номер нити, N - количество строк в матрице
//Проверка не выходим ли за границы матрицы
if (i < N) {
//Умножение части вектора на часть строки
//j - порядковый номер элемента в части вектора или строки матрицы
//чтобы получить реальный номер элемента матрицы
//нужно прибавить j количеству полностью обработанных элементов
for(j = 0; j < THREAD_PER_BLOCK; ++j) {
shared_c[threadIdx.x] += A[i][j + k * THREAD_PER_BLOCK] * shared_vector[j];
}
}
//Синхронизация нужна для того чтобы убедиться
//что все нити закончили работу с частью вектора
//потому что следующая операция - перезапись разделяемой памяти
__syncthread();
}
if ( i < N ) {
С[i] = shared_c[threadId.x];
}
__syncthread();
Модификация кода хоста в этой лабораторной работе не требуется
Для анализа эффективности доступа к разделяемой памяти используйте утилиту nvprof. События для профилирования: shared_ld_bank_conflict – количество конфликтов банков памяти при считывании данных, shared_st_bank_conflict– количество конфликтов банков памяти при записи данных. И метрики: shared_efficiency – эффективность использования пропускной способности шины данных разделяемой памяти, shared_load_transactions_per_request – количество транзакций при каждом запросе к разделяемой памяти.
По аналогии оптимизируйте алгоритм
1. Прочитайте главу из теоретического материала "Разделяемая память" и ответьте на контрольные вопросы (ответы на контрольные вопросы не нужно включать в отчёт по лабораторной работе).
2. Оптимизируйте алгоритмы, реализованные в лабораторной работе №1 при помощи разделяемой памяти.
3. Постройте графики зависимости времени выполнения алгоритма от размера матрицы и вектора (Размеры матрицы 1000x500, 1000x1000, 1500x1000, 2000x1000, 2000x1500, 2500x1500, 2500x2000).
4. Проанализируйте, реализованные алгоритмы при помощи утилиты nvprof на эффективность доступа к глобальной памяти.
Методические указания по выполнению лабораторной работы
Разделяемая память – это своего рода кэш. Ускорения от использования разделяемой памяти можно достичь только если к каким-то данным происходит многократное обращение. Тогда переместив их в разделяемую память из глобальной можно сократить время затраченное на обращение в память за счёт высокой скорости разделяемой памяти.
Рассмотрим схему параллельного умножения матрицы на вектор.
Рис. 1 – схема умножения матрицы на вектор
Каждая нить берёт по одной строке матрицы и умножает попарно элементы строки на элементы вектора. Все нити используют один и тот же вектор. Скопировав вектор в разделяемую память можно получить ускорения выполнения алгоритма. Но проблема разделяемой памяти в том, что её объём очень мал по сравнению с объёмом глобальной памяти. Поэтому нужно предусмотреть ситуацию когда вектор полностью в память не помещается.
Учитывая, что разделяемой памяти может не хватить нужно модифицировать алгоритм таким образом чтобы часть вектора копировалась в разделяемую память. Нити умножали часть строки на часть вектора, расположенного в разделяемой памяти. Затем копировали следующую часть вектора в разделяемую память и умножали элементы следующей части строки и т.д. как показано на рисунке 2.
Рис. 2 – умножение нитью строки на вектор с копированием частей вектора в разделяемую память
Копирование частей вектора можно производить параллельно, каждая нить может копировать в разделяемую память один или несколько элементов. Таким образом псевдокод алгоритма будет выглядеть следующим образом:
//Выделяем разделяемую память
//Количество элементов будет равно количеству нитей в блоке.
__shared__ shared_vector[THREAD_PER_BLOCK];
//k - номер части вектора. +1 потому что M не обязательно делится нацело
for(k = 0; k < (M / THREAD_PER_BLOCK) + 1; ++k) {
//p - реальный номер элемента вектора
//который будет скопирован нитью в разделяемую память
p = threadIdx.x + THREAD_PER_BLOCK * k;
//Проверка на выход за пределы вектора
if(p < M) {
//Копирование из глобальной памяти в разделяемую
//Т.к. размер разделяемой памяти равен размеру блока
//Каждая нить может скопировать по одному элементу
shared_vector[threadIdx.x] = V[threadIdx.x + THREAD_PER_BLOCK * k];
}
//Синхронизация. Нужно дождаться пока все нити скопируют свои элементы
//Потому что каждая нить использует скопированную часть вектора полностью
__syncthread();
//i - глобальный номер нити, N - количество строк в матрице
//Проверка не выходим ли за границы матрицы
if (i < N) {
//Умножение части вектора на часть строки
//j - порядковый номер элемента в части вектора или строки матрицы
//чтобы получить реальный номер элемента матрицы
//нужно прибавить j количеству полностью обработанных элементов
for(j = 0; j < THREAD_PER_BLOCK; ++j) {
C[i] += A[i][j + k * THREAD_PER_BLOCK] * shared_vector[j];
}
}
//Синхронизация нужна для того чтобы убедиться
//что все нити закончили работу с частью вектора
//потому что следующая операция - перезапись разделяемой памяти
__syncthread();
}
В данном коде можно сделать ещё одну оптимизацию – перенести операции над вектором C в разделяемую память. И скопировать результат в глобальную только после того как результат будет посчитан. С учётом этого алгоритм будет выглядеть следующим образом:
//Выделяем разделяемую память
//Количество элементов будет равно количеству нитей в блоке.
__shared__ shared_vector[THREAD_PER_BLOCK];
__shared__ shared_c[THREAD_PER_BLOCK];
shared_c[threadId.x] = 0;
__syncthread();
//k - номер части вектора. +1 потому что M не обязательно делится нацело
for(k = 0; k < (M / THREAD_PER_BLOCK) + 1; ++k) {
//p - реальный номер элемента вектора
//который будет скопирован нитью в разделяемую память
p = threadIdx.x + THREAD_PER_BLOCK * k;
//Проверка на выход за пределы вектора
if(p < M) {
//Копирование из глобальной памяти в разделяемую
//Т.к. размер разделяемой памяти равен размеру блока
//Каждая нить может скопировать по одному элементу
shared_vector[threadIdx.x] = V[threadIdx.x + THREAD_PER_BLOCK * k];
}
//Синхронизация. Нужно дождаться пока все нити скопируют свои элементы
//Потому что каждая нить использует скопированную часть вектора полностью
__syncthread();
//i - глобальный номер нити, N - количество строк в матрице
//Проверка не выходим ли за границы матрицы
if (i < N) {
//Умножение части вектора на часть строки
//j - порядковый номер элемента в части вектора или строки матрицы
//чтобы получить реальный номер элемента матрицы
//нужно прибавить j количеству полностью обработанных элементов
for(j = 0; j < THREAD_PER_BLOCK; ++j) {
shared_c[threadIdx.x] += A[i][j + k * THREAD_PER_BLOCK] * shared_vector[j];
}
}
//Синхронизация нужна для того чтобы убедиться
//что все нити закончили работу с частью вектора
//потому что следующая операция - перезапись разделяемой памяти
__syncthread();
}
if ( i < N ) {
С[i] = shared_c[threadId.x];
}
__syncthread();
Модификация кода хоста в этой лабораторной работе не требуется
Для анализа эффективности доступа к разделяемой памяти используйте утилиту nvprof. События для профилирования: shared_ld_bank_conflict – количество конфликтов банков памяти при считывании данных, shared_st_bank_conflict– количество конфликтов банков памяти при записи данных. И метрики: shared_efficiency – эффективность использования пропускной способности шины данных разделяемой памяти, shared_load_transactions_per_request – количество транзакций при каждом запросе к разделяемой памяти.
По аналогии оптимизируйте алгоритм
Дополнительная информация
зачет
Похожие материалы
Программирование графических процессоров. Лабораторная работа №2
pleze
: 20 марта 2022
Тема: Работа с разделяемой памятью
Задание
1. Прочитайте главу из теоретического материала "Разделяемая память" и ответьте на контрольные вопросы (ответы на контрольные вопросы не нужно включать в отчёт по лабораторной работе).
2. Оптимизируйте алгоритмы, реализованные в лабораторной работе №1 при помощи разделяемой памяти.
3. Постройте графики зависимости времени выполнения алгоритма от размера матрицы и вектора (Размеры матрицы 1000x500, 1000x1000, 1500x1000, 2000x1000, 2000x1500, 2500x1500, 2
300 руб.
Лабораторная работа 2 Программирование графических процессоров Все варианты 2023 год
SibSUTTI
: 1 сентября 2023
2023 год
СибГУТИ
Сибирский государственный университет телекоммуникаций и информатики
Милешко Антон Владимирович
Тема: Лабораторная работа 1 2 3 Программирование графических процессоров Все варианты 2023 год
Задания
Лабораторная работа №2 по курсу «Программирование графических процессоров» на тему «Работа с разделяемой памятью»
Выполнение лабораторной работы поможет получить навыки требующиеся для выполнения второго и третьего заданий контрольной работы.
Задание
1. Прочитайте главу из теоретич
198 руб.
Лабораторная работа 1 2 3 Программирование графических процессоров Все варианты 2023 год
Alexey312451
: 16 марта 2024
Выполнение лабораторной работы поможет получить навыки, требующиеся для выполнения первого и третьего заданий контрольной работы.
Задание
1. Прочитайте главы теоретического материала под названиями "Отличия GPU от CPU", "Первая программа на CUDA C", "Алгоритм сложения двух векторов на GPU", "События, обработка ошибок и получение информации об устройстве", "Глобальная, локальная и константная память". Ответьте на контрольные вопросы и выполните контрольные задания, предложенные в конце этих глав
400 руб.
Лабораторная работа 1 2 3 Программирование графических процессоров Все варианты 2023 год
SibSUTTI
: 1 сентября 2023
2023 год
СибГУТИ
Сибирский государственный университет телекоммуникаций и информатики
Милешко Антон Владимирович
Тема: Лабораторная работа 1 2 3 Программирование графических процессоров Все варианты 2023 год
Задания
Лабораторная работа №1 по курсу «Программирование графических процессоров» на тему «Работа с глобальной памятью»
Выполнение лабораторной работы поможет получить навыки, требующиеся для выполнения первого и третьего заданий контрольной работы.
Задание
1. Прочитайте главы теоретическ
498 руб.
Лабораторная работа №2 "Работа с разделяемой памятью" по дисциплине "Программирование графических процессоров". Вариант общий
vpozyaikin
: 1 марта 2021
Выполнение лабораторной работы поможет получить навыки требующиеся для выполнения второго и третьего заданий контрольной работы.
Задание
1. Прочитайте главу из теоретического материала "Разделяемая память" и ответьте на контрольные вопросы (ответы на контрольные вопросы не нужно включать в отчёт по лабораторной работе).
2. Оптимизируйте алгоритмы, реализованные в лабораторной работе №1 при помощи разделяемой памяти.
3. Постройте графики зависимости времени выполнения алгоритма от размера матрицы
500 руб.
Лабораторная работа 2 (Вариант 3) По дисциплине: Программирование графических процессоров. Тема: «Работа с разделяемой памятью».
alexadubinina
: 21 ноября 2024
Задание
1. Прочитайте главу из теоретического материала "Разделяемая память" и ответьте на контрольные вопросы (ответы на контрольные вопросы не нужно включать в отчёт по лабораторной работе).
2. Оптимизируйте алгоритмы, реализованные в лабораторной работе №1 при помощи разделяемой памяти.
3. Постройте графики зависимости времени выполнения алгоритма от размера матрицы и вектора (Размеры матрицы 1000x500, 1000x1000, 1500x1000, 2000x1000, 2000x1500, 2500x1500, 2500x2000).
4. Проанализируйте, реал
300 руб.
Другие работы
Шпаргалка по химии на экзамены и тесты
GAGARIN
: 28 января 2012
Все темы, понятия и определения в кратком изложении, Ответы на вопросы к экзаменам.
Д.И. Соколов Шпаргалки по химии в электронном виде.
СОДЕРЖАНИЕ
1. Предмет и задачи химии 3
2. Строение атомов химических элементов. Изотопы 3
3. Основные понятия и законы химии 5
4. Ядерные реакции. Радиоактивность 7
5. Периодический закон Д. И. Менделеева 7
6. Строение атома и его электронной оболочки 9
7. Химическая связь 11
8. Скорость химических реакций.... 11
9. Растворы. Растворимость 13
10. Гидролиз 13
25 руб.
Экзаменационная работа пл безопасности жизнедеятельности Билет №7
nat2744
: 24 апреля 2010
СибГУТИ. Билет №7.
1.Органы управления безопасностью труда, надзора и контроля за охраной труда.
2. Защитное отключение в электроустановках. Определение, назначение, схема, область применения, принцип действия.
3. Решить задачу
В электрической сети (трехфазной трехпроводной, с изолированной нейтралью) напряжением 380/220 В фаза С вследствие повреждения изоляции оказалась замкнутой на корпус заземленной электроустановки, которой касается человек, а фаза В замкнулась на землю, при этом сопротивлен
100 руб.
Референдум в системе демократии
Slolka
: 6 июля 2013
Референдум и свободные выборы определяются как высшее непосредственное выражение власти народа. Тем самым устанавливается высший авторитет решений, принятых на референдуме и результатов свободных выборов. В то же время для эффективного осуществления народовластия необходимо достижения оптимального баланса различных его форм. Так, в соответствии с мировым опытом по определенным вопросам (налоги, бюджет, регулирование прав человека и т.п.) считается нецелесообразным проводить референдумы
10 руб.
Задание к теме 4 по предмету: Бюджетный учет
Andreas74
: 21 сентября 2023
Задание к теме 4: Учет обязательств бюджетных учреждений
Задача 1. На основании исходных данных, оформить заявки на кассовый расход в орган федерального казначейства.
Занести данные из первичных документов в Журнал операций по безналичным расчетам.
Перечислено поставщику ООО «ПромТранс» с лицевого счета, открытого в органе казначейства за транспортные услуги –20 000руб.
Перечислено ООО «Водоканал» за оказанные коммунальные услуги –
50 000 руб.
Перечислена заработная плата сотрудникам учрежден
130 руб.