Практикум по программированию
Любая симуляция N-body - симуляция динамической системы, развивающейся под воздействием физических сил. Обзор реализации симуляции N-body. Вычисление гистограммы с помощью атомарных функций. Переборка в CUDA с использованием динамического параллелизма.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | реферат |
Язык | русский |
Дата добавления | 24.11.2022 |
Размер файла | 1,1 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://allbest.ru
Размещено на http://allbest.ru
Федеральное государственное автономное образовательное учреждение
высшего образования
Санкт-Петербургский политехнический университет Петра Великого
Институт компьютерных наук и технологий
Высшая школа «Киберфизические системы и управление»
Реферат
по дисциплине «Практикум по Программированию»
Выполнил:
студент гр. з3530902/00001
Кузнецов Р.О.
Руководитель:
ст. преподаватель
Жиленков А.А.
Санкт-Петербург
2022
N-тело
Любая симуляция N-body - это симуляция динамической системы, развивающейся под воздействием физических сил. Численная аппроксимация выполняется по мере того, как тела непрерывно взаимодействуют друг с другом. Моделирование N-body широко применяется в физике и астрономии, например, для того, чтобы ученые могли понять динамику частиц во Вселенной. Моделирование N-тел используется во многих других областях, включая вычислительную гидродинамику для понимания моделирования турбулентных потоков жидкости.
Относительно простой метод решения моделирования N-тел заключается в использовании метода грубой силы, техника, которая имеет O() сложность. Этот подход неудобен по своей параллельной природе. Существуют различные оптимизации на уровне алгоритмов, которые могут уменьшить сложность вычислений. сложность. Вместо того чтобы применять метод всех пар ко всей симуляции, его можно использовать для определения сил во взаимодействиях на близких расстояниях. Даже в этом случае создание ядра для решения сил на CUDA очень полезно, так как это также улучшит производительность компонентов дальнего поля. Ускорение одного компонента разгружает работу других компонентов, поэтому все приложение выигрывает от ускорения одного ядра.
Реализация моделирования N тел на GPU
Алгоритм в основном представляет собой алгоритм расчета силы, , для сетки из тел. Общая сила/ускорение, , на тело, i, является результатом суммирования всех записей в строке i. С точки зрения параллелизма, это неловко параллельная задача O().
С точки зрения производительности, приложение ограничено памятью и будет ограничено пропускной способностью памяти. Хорошо то, что большая часть данных может быть использована повторно и храниться в памяти с высокой пропускной способностью и низкой задержкой, такой как общая память. Повторное использование и хранение данных в общей памяти снижает нагрузку на глобальную память и, следовательно, помогает достичь пиковой производительности вычислений.
На следующей диаграмме показана стратегия, которую мы будем использовать:
Вместо того чтобы снова и снова загружать память из глобальной памяти, мы используем плитку. На предыдущей диаграмме показано, что каждая строка вычисляется параллельно. Размер тайла определяется максимальным количеством элементов, которые можно хранить в общей памяти, что не влияет на загрузку ядра. Каждый блок загружает данные в общую память, после чего выполняется синхронизация. Как только данные были загружены в общую память, расчет силы/ускорения выполняется в каждом блоке. Видно, что хотя отдельный ряд вычисляется параллельно, для достижения оптимального повторного использования данных, взаимодействие в каждом ряду выполняется последовательно.
Обзор реализации симуляции N-body
Рассмотрим реализацию этого в формате псевдокода, а затем объясним ее логику. В этом примере мы используем гравитационный потенциал, чтобы проиллюстрировать основную форму вычислений в моделировании всех пар N-тел. Реализованный код можно найти в 07_parallel_programming_pattern/05_n-body. Для начала работы выполняем следующие шаги:
1. Инициализируем n-пространство случайными переменными
Data [i] = 2.0f * (rand()/max ) - 1.0f
2. Хранение данных в промежуточном разделяемом пространстве памяти для эффективного повторного использования. Синхронизируем его, чтобы гарантировать, что все потоки внутри блока видят обновленные значения в общей памяти:
for (int tile = 0; tille < gridDim.x; tile++) {
..._shared_ float3 shared_position[blockDim.x];
float4 temp_position = p[tile * blockDim.x + threadIdx.x];
shared_position [threadIdx.x]
= make_float3(temp_position.x, temp_position.y, temp_position.z);
_syncthreads();
...
}
3. Рассчитываем силу путем итерации каждого блока:
for (int j = 0; j < BLOCK_SIZE; j++) {
// Calculate Force
_synccthreads();
}
4. Наконец, скомпилируем приложение с помощью компилятора OWDD с помощью следующей командой:
$nvcc -run --gpu-architecture=sm_70 -o n-body n_body.cu
Как видно, реализация симуляции N тел является неловко параллельной задачей и довольно простой. Хотя мы реализовали здесь базовую версию кода, существуют различные алгоритмические вариации. Можно использовать эту версию в качестве шаблона который можно улучшить, основываясь на изменениях, внесенных в алгоритм.
Вычисление гистограммы
В неловко параллельной работе, в идеале, вы должны поручить вычисления каждому потоку работающим с независимыми данными, что исключает гонки данных. К настоящему времени мы поняли, что некоторые модели не подходят под эту категорию. Один из таких примеров - когда мы вычисляем гистограмму. Шаблон гистограммы отображает частоту элемента данных, например, количество раз, когда мы использовали слово CUDA в каждой главе, количество раз, когда каждая буква встречалась в этой главе, и так далее. Гистограмма имеет следующий вид:
симуляция динамическая система гистограмма вычисление атомарные функции
В этом разделе использую атомарные операции для сериализации доступа к данным, чтобы получить правильные результаты.
Этапы компиляции и выполнения
Гистограмма предоставляет важные характеристики имеющихся наборов данных, а также полезные сведения о них. Например, из всего изображения есть только несколько областей, в которых могут находиться интересующие вас области. Создание гистограммы иногда используется для того, чтобы определить, где на изображении может находиться интересующая область. В этом примере использую расчет гистограммы на изображении, где все изображение разделено на фрагменты.
1. Подготавливаю приложение для GPU. Этот код можно найти
07_parallel_programming_pattern/08_histogram.
2. Скомпилирую приложение с помощью компилятора OWDD с помощью следующей команды:
$ nvcc -c scrImagePgmPpmPackage.cpp
$ nvcc -c image_histogram.cu
$ nvcc -run -o image_histogram image_histogram.o
scrImagePgmPpmPackage.o
ScrImagePgmPpmPackage.cpp предоставляет исходный код, который мы можем использовать для чтения и записи изображений с расширениями QHN. Код расчета гистограммы можно найти в image_histogram.cu.
Понимание параллельной гистограммы
Такие паттерны, как гистограмма, требуют атомарных операций, что означает обновление значения по определенному адресу в последовательном режиме, чтобы устранить разногласия между несколькими потоками, тем самым обновляя один и тот же адрес. Это требует координации между несколькими потоками.
Приватизация - это техника, которая использует память с низкой задержкой, такую как общая память, для снижения пропускной способности и уменьшения задержки, как показано на следующей диаграмме:
По сути, вместо использования атомарных операций в глобальной памяти, мы используем атомарные операции над общей памятью. Причина очевидна. Атомарные операции в глобальной памяти более дорогостоящие по сравнению с выполнением тех же операций в общей памяти/кэша L1. Начиная с архитектуры Maxwell и далее, атомарные операции поддерживаются аппаратно. Реализация приватизированной общей памяти в идеале должна давать 2х-кратную производительность, начиная с архитектуры Maxwell и далее. Однако атомарные операции ограничены определенными функциями и размерами данных.
Вычисление гистограммы с помощью атомарных функций
CUDA функции
В первую очередь мы будем использовать операцию AtomicAdd () операцию над общей памятью, чтобы вычисления гистограммы для каждого блока в общей памяти. Выполняю следующие шаги для вычисления гистограммы в ядре:
1. Выделяю общую память на блок, равный размеру гистограммы на блок. Поскольку это изображение в формате char элементы будут находиться в диапазоне 0-255:
_shared_ unsigned int histo_private [256] ;
2. Инициализируйте массив общей памяти для каждого блока:
if (localId <256)
histo_private [localId] = 0 ;
3. Синхронизируйте это, чтобы убедиться, что все потоки в блоке видят инициализированный массив:
_syncthreads () ;
4. Считывание данных изображения из глобальной памяти текстур:
unsigned char imageData = text2D<unsigned
char> (texObj, (float) (tidX) , (float) (tidY) ) ;
5. Выполните операцию AtomicAdd () операцию над общей памятью:
atomicAdd (&(histo_private [imageData] ), 1) ;
6. Синхронизация по блоку перед записью в глобальную память:
_syncthreads ();
7. Запишите гистограмму на блок в глобальную память:
if (localId <256)
imageHistogram [histStartIndex+localId] =
histo_private [localId] ;
Теперь мы закончили реализацию вычисления гистограммы на GPU. Подводя итог, можно сказать, что гистограммы легко реализовать с помощью общей атомарной памяти. Этот подход может достичь высокой производительности на картах Maxwell и далее благодаря встроенной аппаратной поддержке разделяемой атомарной памяти.
Переборка в CUDA с использованием динамического параллелизм
Одним из ключевых алгоритмов, который является фундаментальным строительным блоком для любого приложения, является сортировка. Существует множество алгоритмов сортировки, которые были подробно изучены. Некоторые алгоритмы сортировки относятся к категории "разделяй и властвуй". Эти алгоритмы подходят для параллелизма и подходят для таких архитектур, как GPU где данные, подлежащие сортировке, могут быть разделены для сортировки. Одним из таких алгоритмов является Quicksort. Он представляет собой трехэтапный подход, который заключается в следующем:
1. Выберите элемент из массива, который необходимо отсортировать. Этот элемент действует как поворотный элемент.
2. Вторым шагом является разбиение на разделы, куда попадают все элементы. Все элементы, которые меньше поворотного элемента, сдвигаются влево, а все элементы, которые больше или равны стержню, сдвигаются вправо от стержневого элемента. Этот шаг также известен как разбиение на разделы.
3. Рекурсивно выполняйте шаги 1 и 2, пока все подмассивы не будут отсортированы.
Наихудшая сложность Quicksort составляет O(), что может показаться не идеальным по сравнению с другими процессами сортировки. процессами сортировки, сложность которых в наихудшем случае равна O() ), такими как сортировка слиянием и y heap sort). Однако на практике видно, что Quicksort эффективен. Выбор поворотного элемент может быть выбран с учетом, а иногда и случайно, так что сложность в худшем случае сложность практически не возникает. Кроме того, видно, что Quicksort меньше загружает память и имеет меньшие по сравнению с другими алгоритмами сортировки, такими как сортировка слиянием, которая требует дополнительного хранилища. В более практических реализациях Quicksort используется рандомизированная версия. На сайте рандомизированная версия имеет ожидаемую временную сложность O( ). В худшем случае сложность также возможна в рандомизированной версии, но она не возникает для определенного шаблона (например, отсортированного массива), и рандомизированная версия Quicksort хорошо работает на практике. Хотя можно написать целую главу об особенностях алгоритма сортировки, я планирую рассмотреть только те возможности CUDA, которые помогут эффективно реализовать Quicksort на GPU. В этом разделе мы будем использовать динамический параллелизм, который был введен начиная с CUDA 6.0 и GPU с архитектурой 3.5 и выше. Итак, рассмотрим, какой вклад вносит динамический параллелизм в алгоритм сортировки.
Quicksort и динамический параллелизм CUDA
Алгоритм Quicksort требует рекурсивного запуска ядер. До сих пор алгоритмы, которые мы рассматривали, вызывали ядро один раз через CPU. После того как ядро завершает выполнение, мы возвращаемся к потоку CPU и снова запускаем его. Это приводит к передаче управления CPU, а также может привести к передаче данных между CPU и GPU, что является дорогостоящей операцией. Раньше было очень сложно эффективно реализовать такие алгоритмы, как Quicksort на графических процессорах, которые требуют таких функций, как рекурсия. С архитектурой GPU 3.5 и CUDA 5.0 была введена новая функция, называемая динамическим параллелизмом. Динамический параллелизм позволяет потокам внутри ядра запускать новые ядра с GPU без возврата управления обратно. GPU без возврата управления обратно на CPU. Слово динамический происходит от того, что что он динамически основывается на данных времени выполнения. Несколько ядер могут быть запущены потоками одновременно. Следующая диаграмма упрощает это объяснение:
Если бы мы перевели эту концепцию на то, как выполняется Quicksort, то это выглядело бы примерно так примерно так:
Глубина 0 - это вызов от центрального процессора. Для каждого подмассива мы запускаем два ядра: одно для левого и одно для правого массивов. массива и одно для правого массива. Рекурсия останавливается после того, как максимальная глубина ядра будет или количество элементов становится меньше 32, что является размером искривления. Для того чтобы ядро запуск ядра должен быть в ненулевом потоке и асинхронным, чтобы ядро подмассива запускалось независимо, нам нужно создать поток перед каждым запуском ядра:
cudaStream_t s ;
cudaStreamCreatWithFlags (&s, cudaSteamNonBlocking ) ;
cpd_simple_quicksort <<< 1, 1, 0, s>>> (data, left, nright, depth+1);
cudaStreamDestroy ( s ) ;
Это действительно важный шаг, потому что в противном случае запуск ядра может быть сериализован. Для получения более подробной информации о потоках обратитесь к ядру multi-GPU.
Размещено на Allbest.ru
...Подобные документы
Графический ввод схемы и симуляция в Quartus II. Основные логические элементы. Описание логических схем при помощи языка AHDL, его элементы. Зарезервированные ключевые слова. Моделирование цифровых схем с использованием параметрических элементов.
курсовая работа [1,7 M], добавлен 07.06.2015Сравнение трех CAD/CAM систем: Cimatron, MasterCam, Solid Edge. Симуляция процесса черновой и чистовой фрезерной обработки. Таблицы настройки технологических параметров обработки. Фотовизуализации моделей Mastercam Design. Поверхностное моделирование.
реферат [2,2 M], добавлен 24.02.2013Сравнение центрального и графического процессора компьютера в параллельных расчётах. Пример применения технологии CUDA для неграфических вычислений. Вычисление интеграла и сложение векторов. Технические характеристики ПК, применяемого для вычислений.
курсовая работа [735,9 K], добавлен 12.07.2015Загальна термінологія CUDA. Структура NVIDIA CUDA, особливості створення, принципи оптимізації програм. Проблеми CUDA. Основні поняття і модель програмування, демонстрація технології CUDA на прикладі підрахунку CRC32-коду. Мінімальні вимоги до програми.
курсовая работа [4,5 M], добавлен 14.05.2012Анализ системы дистанционного практикума по программированию. Модернизация ядра системы для работы с новым конфигурационным файлом. Программная реализация изменений в базе данных и веб-интерфейсе пользователя. Разработка инструкции для участника олимпиад.
дипломная работа [1,1 M], добавлен 09.11.2016Еволюція GPU та поява GPGPU. OpenCL – відкритий стандарт для паралельного програмування гетерогенних систем. Сутність та особливості технології Nvidia CUDA. Програмно-апаратна платформа CUDA. Програмування за допомогою CUDA SDK. Огляд архітектури Fermi.
курсовая работа [3,0 M], добавлен 09.06.2012Создание динамической модели табеля учета рабочего времени. Формирование счетчика с 1901 по 2012. Формат ячеек. Условный формат для выходных дней. Проектирование динамической модели календаря с помощью именованных констант. Вычисление дат понедельников.
курсовая работа [6,5 M], добавлен 15.02.2015Преимущества архитектуры CUDA по сравнению с традиционным подходом к организации вычислений общего назначения посредством возможностей графических API. Создание CUDA проекта. Код программы расчёта числа PI и суммирования вектора CPU, ее технический вывод.
курсовая работа [1,4 M], добавлен 12.12.2012Программно-аппаратный комплекс производства компании Nvidia. Код для сложения векторов, представленный в CUDA. Вычислительная схема СPU с несколькими ядрами SMP. Выделение памяти на видеокарте. Проведение синхронизации работы основной и GPU программ.
презентация [392,5 K], добавлен 14.12.2013Создание программы, которая создает набор данных в динамической памяти компьютера и позволяет корректировать его. Описание программного комплекса. Обзор особенностей реализации программы с использованием модулей. Добавление данных в конец текущего набора.
курсовая работа [455,2 K], добавлен 28.08.2017Вычисление значений выражений при вещественных типах данных float и double. Нахождение суммы элементов, используя оператор цикла. Вычисление функций с разложением в степенной ряд. Работа со строками. Обработка массивов с использованием функций.
лабораторная работа [24,3 K], добавлен 09.02.2010Постановка задачи динамического программирования. Поведение динамической системы как функция начального состояния. Математическая формулировка задачи оптимального управления. Метод динамического программирования. Дискретная форма вариационной задачи.
реферат [59,9 K], добавлен 29.09.2008Поиск источников ориентированного графа. Использование динамических структур при работе с графами. Способы представления графов, операции над ними, описание программной реализации. Процедуры и функции языка. Функции работы с динамической памятью, графами.
курсовая работа [58,6 K], добавлен 29.01.2009- Разработка и исследования метода сетевого оператора для адаптивного управления динамическим объектом
Генетическое программирование и алгоритм. Метод сетевого оператора. Матрица, вариации и вектор сетевого оператора. Метод интеллектуальной эволюции. Сетевой оператор базового решения. Движение робота в плоскости X,Y, симуляция с начальными условиями.
дипломная работа [2,6 M], добавлен 23.09.2013 Понятие и особенности организации технологии CUDA, принципы реализации алгоритма с его помощью. Генерация случайных чисел. Оценка производительности исследуемой технологии, специфика построения графических программ на основе, преимущества использования.
контрольная работа [102,7 K], добавлен 25.12.2014Обзор задач, решаемых методом динамического программирования. Составление маршрута оптимальной длины. Перемножение цепочки матриц. Задача "Лестницы". Анализ необходимости использования специальных методов вероятностного динамического программирования.
курсовая работа [503,3 K], добавлен 28.06.2015Основные теги для создания сайтов. Вложенные атрибуты элемента "BODY". Вставки в документ графического изображения. Внедрение таблиц в Web страницу. Гиперссылки, изображения и формы. Страница приветствия, главная страница: палеолит, мезолит, неолит.
практическая работа [39,2 K], добавлен 02.03.2011Общие сведения о системе Mathcad. Окно программы Mathcad и панели инструментов. Вычисление алгебраических функций. Интерполирование функций кубическими сплайнами. Вычисление квадратного корня. Анализ численного дифференцирования и интегрирования.
курсовая работа [522,7 K], добавлен 25.12.2014Оценка качества подготовки программистов и снижение трудозатрат на подготовку и проверку их лабораторных работ. Разработка проекта по автоматизации процесса обучения программированию с помощью интегрированной среды оценки структуры и качества программы.
дипломная работа [2,5 M], добавлен 07.06.2012Полное описание работы с алгоритмами запросов, используемых программой по сбору информации о доходах физических лиц для формирования налоговых документов. Построение организационно-управленческой модели программы. Состав функций реализуемых системой.
дипломная работа [3,8 M], добавлен 28.06.2011