Параллельные и высокопроизводительные вычисления

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

Параллельное программирование позволяет распределять задачи обработки данных между несколькими процессорами, существенно повышая производительность. В книге рассказывается, как с минимальными трудозатратами повысить эффективность ваших программ. Вы научитесь оценивать аппаратные архитектуры и работать со стандартными инструментами отрасли, такими как OpenMP и MPI, освоите структуры данных и алгоритмы, подходящие для высокопроизводительных вычислений, узнаете, как экономить энергию на мобильных устройствах, и даже запустите масштабную симуляцию цунами на батарее из GPU-процессоров. Издание предназначено для опытных программистов, владеющих языком высокопроизводительных вычислений, таким как C, C++ или Fortran.

Author(s): Роберт Роби, Джулиана Замора
Edition: 1
Publisher: ДМК Пресс
Year: 2021

Language: Russian
Commentary: Vector PDF
Pages: 800
City: М.
Tags: Parallel Programming; Filesystems; Docker; Benchmarking; Profiling; GPU Programming; HDF5; Hash Functions; SIMD; OpenMP; CUDA; Nvidia; High Performance Computing; Algorithm Analysis; Version Control Systems; Algorithm Complexity; OpenCL; VirtualBox; Message Passing Interface

Оглавление
Предисловие
Благодарности
О книге
Об авторах
Об иллюстрации на обложке
Часть I. Введение в параллельные вычисления
Глава 1. Зачем нужны параллельные вычисления?
1.1 Почему вы должны изучить параллельные вычисления?
1.1.1 Каковы потенциальные преимущества параллельных вычислений?
1.1.2 Предостережения, связанные с параллельными вычислениями
1.2 Фундаментальные законы параллельных вычислений
1.2.1 Предел на параллельные вычисления: закон Амдала
1.2.2 Преодоление параллельного предела: закон Густафсона–Барсиса
1.3 Как работают параллельные вычисления?
1.3.1 Пошаговое ознакомление с примером приложения
1.3.2 Аппаратная модель для современных гетерогенных параллельных систем
1.3.3 Прикладная/программная модель для современных гетерогенных параллельных систем
1.4 Классифицирование параллельных подходов
1.5 Параллельные стратегии
1.6 Параллельное ускорение против сравнительного ускорения: две разные меры
1.7 Чему вы научитесь в этой книге?
1.7.1 Дополнительное чтение
1.7.2 Упражнения
Резюме
Глава 2. Планирование под параллелизацию
2.1 На подступах к новому проекту: подготовка
2.1.1 Версионный контроль: создание безопасного хранилища для своего параллельного кода
2.1.2 Комплекты тестов: первый шаг к созданию устойчивого и надежного приложения
2.1.3 Отыскание и исправление проблем с памятью
2.1.4 Улучшение переносимости кода
2.2 Профилирование: определение разрыва между способностями системы и производительностью приложения
2.3 Планирование: основа успеха
2.3.1 Разведывательный анализ с использованием сравнительных тестов и мини-приложений
2.3.2 Дизайн стержневых структур данных и модульность кода
2.3.3 Алгоритмы: редизайн для параллельности
2.4 Имплементация: где все это происходит
2.5 Фиксация: качественное завершение работы
2.6 Материалы для дальнейшего изучения
2.6.1 Дополнительное чтение
2.6.2 Упражнения
Резюме
Глава 3. Пределы производительности и профилирование
3.1 Знание потенциальных пределов производительности вашего приложения
3.2 Определение возможностей своего оборудования: сравнительное тестирование
3.2.1 Инструменты для сбора характеристик системы
3.2.2 Расчет теоретических максимальных флопов
3.2.3 Иерархия памяти и теоретическая пропускная способность памяти
3.2.4 Эмпирическое измерение пропускной способности и флопов
3.2.5 Расчет машинного баланса между флопами и пропускной способностью
3.3 Характеризация вашего приложения: профилирование
3.3.1 Инструменты профилирования
3.3.2 Эмпирическое измерение тактовой частоты и энергопотребления процессора
3.3.3 Отслеживание памяти во время выполнения
3.4 Материалы для дальнейшего изучения
3.4.1 Дополнительное чтение
3.4.2 Упражнения
Резюме
Глава 4. Дизайн данных и модели производительности
4.1 Структуры данных для обеспечения производительности: дизайн с ориентацией на данные
4.1.1 Многомерные массивы
4.1.2 Массив структур (AoS) против структур из массивов (SoA)
4.1.3 Массив структур из массивов (AoSoA)
4.2 Три категории неуспешных обращений к кешу: вынужденное, емкостное и конфликтное
4.3 Простые модели производительности: тематическое исследование
4.3.1 Полноматричные представления данных
4.3.2 Представление сжато-разреженного хранения
4.4 Продвинутые модели производительности
4.5 Сетевые сообщения
4.6 Материалы для дальнейшего изучения
4.6.1 Дополнительное чтение
4.6.2 Упражнения
Резюме
Глава 5. Параллельные алгоритмы и шаблоны
5.1 Анализ алгоритмов для приложений параллельных вычислений
5.2 Модели производительности против алгоритмической сложности
5.3 Параллельные алгоритмы: что это такое?
5.4 Что такое хеш-функция?
5.5 Пространственное хеширование: высокопараллельный алгоритм
5.5.1 Использование идеального хеширования для пространственных операций с сеткой
5.5.2 Использование компактного хеширования для пространственных операций на сетке
5.6 Шаблон префиксного суммирования (сканирования) и его важность в параллельных вычислениях
5.6.1 Операция параллельного сканирования с эффективностью шагов
5.6.2 Операция параллельного сканирования с эффективностью работы
5.6.3 Операции параллельного сканирования для крупных массивов
5.7 Параллельная глобальная сумма: решение проблемы ассоциативности
5.8 Будущие исследования параллельных алгоритмов
5.9 Материалы для дальнейшего изучения
5.9.1 Дополнительное чтение
5.9.2 Упражнения
Резюме
Часть II. CPU: параллельная рабочая лошадка
Глава 6. Векторизация: флопы забесплатно
6.1 Векторизация и обзор SIMD (одна команда, несколько элементов данных)
6.2 Аппаратные тренды векторизации
6.3 Методы векторизации
6.3.1 Оптимизированные библиотеки обеспечивают производительность за счет малых усилий
6.3.2 Автоматическая векторизация: простой способ ускорения векторизации (в большинстве случаев)
6.3.3 Обучение компилятора посредством подсказок: прагмы и директивы
6.3.4 Дрянные циклы, они у нас в руках: используйте внутренние векторные функции компилятора
6.3.5 Не для слабонервных: применение ассебмлерного кода для векторизации
6.4 Стиль программирования для более качественной векторизации
6.5 Компиляторные флаги, относящиеся к векторизации, для различных компиляторов
6.6 Директивы OpenMP SIMD для более качественной переносимости
6.7 Материалы для дальнейшего изучения
6.7.1 Дополнительное чтение
6.7.2 Упражнения
Резюме
Глава 7. Стандарт OpenMP, который «рулит»
7.1 Введение в OpenMP
7.1.1 Концепции OpenMP
7.1.2 Простая программа стандарта OpenMP
7.2 Типичные варианты использования OpenMP: уровень цикла, высокий уровень и MPI плюс OpenMP
7.2.1 OpenMP уровня цикла для быстрой параллелизации
7.2.2 OpenMP высокого уровня для улучшенной параллельной производительности
7.2.3 MPI плюс OpenMP для максимальной масштабируемости
7.3 Примеры стандартного OpenMP уровня цикла
7.3.1 OpenMP уровня цикла: пример векторного сложения
7.3.2 Пример потоковой триады
7.3.3 OpenMP уровня цикла: стенсильный пример
7.3.4 Производительность примеров уровня цикла
7.3.5 Пример редукции на основе глобальной суммы с использованием потокообразования OpenMP
7.3.6 Потенциальные трудности OpenMP уровня цикла
7.4 Важность области видимости переменной для правильности в OpenMP
7.5 OpenMP уровня функции: придание всей функции целиком свойства поточной параллельности
7.6 Усовершенствование параллельной масштабируемости с помощью OpenMP высокого уровня
7.6.1 Как имплементировать OpenMP высокого уровня
7.6.2 Пример имплементирования OpenMP высокого уровня
7.7 Гибридное потокообразование и векторизация с OpenMP
7.8 Продвинутые примеры использования OpenMP
7.8.1 Стенсильный пример с отдельным проходом для направлений x и y
7.8.2 Имплементация суммирования по Кахану с потокообразованием OpenMP
7.8.3 Поточная имплементация алгоритма префиксного сканирования
7.9 Инструменты потокообразования, необходимые для устойчивых имплементаций
7.9.1 Использование профилировщика Allinea/ARM MAP для быстрого получения высокоуровневого профиля вашего приложения
7.9.2 Отыскание гоночных состояний в потоках с помощью Intel® Inspector
7.10 Пример алгоритма поддержки на основе операционных задач
7.11 Материалы для дальнейшего изучения
7.11.1 Дополнительное чтение
7.11.2 Упражнения
Резюме
Глава 8. MPI: параллельный становой хребет
8.1 Основы программы MPI
8.1.1 Базовые функциональные вызовы MPI для каждой программы MPI
8.1.2 Компиляторные обертки для более простых программ MPI
8.1.3 Использование команд параллельного запуска
8.1.4 Минимально работающий пример программы MPI
8.2 Команды отправки и приемки для обмена данными «из процесса в процесс»
8.3 Коллективный обмен данными: мощный компонент MPI
8.3.1 Использование барьера для синхронизирования таймеров
8.3.2 Использование широковещательной передачи для манипулирования данными малого входного файла
8.3.3 Использование редукции для получения одного единственного значения из всех процессов
8.3.4 Использование операции сбора для наведения порядка в отладочных распечатках
8.3.5 Использование разброса и сбора для отправки данных процессам для работы
8.4 Примеры параллельности данных
8.4.1 Потоковая триада для измерения пропускной способности на узле
8.4.2 Обмен с призрачными ячейками в двухмерной вычислительной сетке
8.4.3 Обмен с призрачными ячейками в трехмерной стенсильной калькуляции
8.5 Продвинутая функциональность MPI для упрощения исходного кода и обеспечения оптимизаций
8.5.1 Использование конкретно-прикладных типов данных MPI для повышения производительности и упрощения кода
8.5.2 Поддержка декартовой топологии в MPI
8.5.3 Тесты производительности вариантов обмена с призрачными ячейками
8.6 Гибридная техника MPI плюс OpenMP для максимальной масштабируемости
8.6.1 Преимущества гибридной техники MPI плюс OpenMP
8.6.2 Пример техники MPI плюс OpenMP
8.7 Материалы для дальнейшего изучения
8.7.1 Дополнительное чтение
8.7.2 Упражнения
Резюме
Часть III. GPU: рождены для ускорения
Глава 9. Архитектуры и концепции GPU
9.1 Система CPU-GPU как ускоренная вычислительная платформа
9.1.1 Интегрированные GPU: недоиспользуемая опция в товарных системах
9.1.2 Выделенные GPU: рабочая лошадка
9.2 GPU и двигатель потокообразования
9.2.1 Вычислительным модулем является потоковый мультипроцессор (или подсрез)
9.2.2 Обрабатывающими элементами являются отдельные процессоры
9.2.3 Несколько операций, выполняемых на данных каждым обрабатывающим элементом
9.2.4 Расчет пиковых теоретических флопов для некоторых ведущих GPU
9.3 Характеристики пространств памяти GPU
9.3.1 Расчет теоретической пиковой пропускной способности памяти
9.3.2 Измерение GPU с помощью приложения STREAM Benchmark
9.3.3 Модель производительности в форме контура крыши для GPU-процессоров
9.3.4 Использование инструмента смешанного сравнительного тестирования производительности для выбора наилучшего GPU для рабочей нагрузки
9.4 Шина PCI: накладные расходы на передачу данных от CPU к GPU
9.4.1 Теоретическая пропускная способность шины PCI
9.4.2 Приложение сравнительного тестирования пропускной способности PCI
9.5 Платформы с многочисленными GPU и MPI
9.5.1 Оптимизирование перемещения данных между GPU-процессорами по сети
9.5.2 Более высокопроизводительная альтернатива шине PCI
9.6 Потенциальные преимущества платформ, ускоренных за счет GPU
9.6.1 Сокращение показателя времени до решения
9.6.2 Сокращение энергопотребления с помощью GPU-процессоров
9.6.3 Снижение в затратах на облачные вычисления за счет использования GPU-процессоров
9.7 Когда следует использовать GPU-процессоры
9.8 Материалы для дальнейшего изучения
9.8.1 Дополнительное чтение
9.8.2 Упражнения
Резюме
Глава 10. Модель программирования GPU
10.1 Абстракции программирования GPU: широко распространенная структура
10.1.1 Массовый параллелизм
10.1.2 Неспособность поддерживать координацию среди операционных задач
10.1.3 Терминология для параллелизма GPU
10.1.4 Декомпозиция данных на независимые единицы работы: NDRange или решетка
10.1.5 Рабочие группы обеспечивают оптимальную по размеру порцию работы
10.1.6 Подгруппы, варпы или волновые фронты исполняются в унисон
10.1.7 Элемент работы: базовая единица операции
10.1.8 SIMD- или векторное оборудование
10.2 Структура кода для модели программирования GPU
10.2.1 Программирование «Эго»: концепция параллельного вычислительного ядра
10.2.2 Поточные индексы: соотнесение локальной плитки с глобальным миром
10.2.3 Индексные множества
10.2.4 Как обращаться к ресурсам памяти в вашей модели программирования GPU
10.3 Оптимизирование использования ресурсов GPU
10.3.1 Сколько регистров используется в моем вычислительном ядре?
10.3.2 Занятость: предоставление большего объема работы для планирования рабочей группы
10.4 Редукционный шаблон требует синхронизации между рабочими группами
10.5 Асинхронные вычисления посредством очередей (потоков операций)
10.6 Разработка плана параллелизации приложения для GPU-процессоров
10.6.1 Случай 1: трехмерная атмосферная симуляция
10.6.2 Случай 2: применение неструктурированной вычислительной сетки
10.7 Материалы для дальнейшего изучения
10.7.1 Дополнительное чтение
10.7.2 Упражнения
Резюме
Глава 11. Программирование GPU на основе директив
11.1 Процесс применения директив и прагм для имплементации на основе GPU
11.2 OpenACC: самый простой способ выполнения на вашем GPU
11.2.1 Компилирование исходного кода OpenACC
11.2.2 Участки параллельных вычислений в OpenACC для ускорения вычислений
11.2.3 Использование директив для сокращения перемещения данных между CPU и GPU
11.2.4 Оптимизирование вычислительных ядер GPU
11.2.5 Резюме результирующих производительностей для потоковой триады
11.2.6 Продвинутые техники OpenACC
11.3 OpenMP: чемпион в тяжелом весе вступает в мир ускорителей
11.3.1 Компилирование исходного кода OpenMP
11.3.2 Генерирование параллельной работы на GPU с по­мощью OpenMP
11.3.3 Создание участков данных для управления перемещением данных на GPU с по­мощью OpenMP
11.3.4 Оптимизирование OpenMP под GPU-процессоры
11.3.5 Продвинутый OpenMP для GPU-процессоров
11.4 Материалы для дальнейшего изучения
11.4.1 Дополнительное чтение
11.4.2 Упражнения
Резюме
Глава 12. Языки GPU: обращение к основам
12.1 Функциональности нативного языка программирования GPU
12.2 Языки CUDA и HIP GPU: низкоуровневая опция производительности
12.2.1 Написание и сборка вашего первого приложения на языке CUDA
12.2.2 Редукционное вычислительное ядро в CUDA: жизнь становится все сложнее
12.2.3 HIP’ифицирование исходного кода CUDA
12.3 OpenCL для переносимого языка GPU с открытым исходным кодом
12.3.1 Написание и сборка вашего первого приложения OpenCL
12.3.2 Редукции в OpenCL
12.4 SYCL: экспериментальная имплементация на C++ становится магистральной
12.5 Языки более высокого уровня для обеспечения переносимости производительности
12.5.1 Kokkos: экосистема обеспечения переносимости производительности
12.5.2 RAJA для более адаптируемого слоя обеспечения переносимости производительности
12.6 Материалы для дальнейшего изучения
12.6.1 Дополнительное чтение
12.6.2 Упражнения
Резюме
Глава 13. Профилирование и инструменты GPU
13.1 Обзор инструментов профилирования
13.2 Как выбрать хороший рабочий поток
13.3 Образец задачи: симуляция мелководья
13.4 Образец профилировочного рабочего потока
13.4.1 Выполнение приложения симуляции мелководья
13.4.2 Профилирование исходного кода CPU для разработки плана действий
13.4.3 Добавление вычислительных директив OpenACC, чтобы начать шаг имплементации
13.4.4 Добавление директив перемещения данных
13.4.5 Направляемый анализ может дать вам несколько предлагаемых улучшений
13.4.6 Комплект инструментов NVIDIA Nsight может стать мощным подспорьем в разработке
13.4.7 CodeXL для экосистемы GPU-процессоров AMD
13.5 Не утоните в болоте: сосредотачивайтесь на важных метриках
13.5.1 Занятость: достаточно ли работы?
13.5.2 Эффективность выдачи: ваши варпы прерываются слишком часто?
13.5.3 Достигнутая пропускная способность: она всегда сводится к пропускной способности
13.6 Контейнеры и виртуальные машины обеспечивают обходные пути
13.6.1 Контейнеры Docker в качестве обходного пути
13.6.2 Виртуальные машины с использованием VirtualBox
13.7 Облачные опции: гибкие и переносимые возможности
13.8 Материалы для дальнейшего изучения
13.8.1 Дополнительное чтение
13.8.2 Упражнения
Резюме
Часть IV. Экосистемы высокопроизводительных вычислений
Глава 14. Аффинность: перемирие с вычислительным ядром
14.1 Почему важна аффинность?
14.2 Нащупывание вашей архитектуры
14.3 Аффинность потоков с OpenMP
14.4 Аффинность процессов с MPI
14.4.1 Принятое по умолчанию размещение процессов с по­мощью OpenMPI
14.4.2 Взятие под контроль: базовые техники специфицирования размещения процессов в OpenMPI
14.4.3 Аффинность – это больше, чем просто привязывание процессов: полная картина
14.5 Аффинность для MPI плюс OpenMP
14.6 Контроль за аффинностью из командной строки
14.6.1 Использование инструмента hwloc-bind для назначения аффинности
14.6.2 Использование likwid-pin: инструмент аффинности в комплекте инструментов likwid
14.7 Будущее: установка и изменение аффинности во время выполнения
14.7.1 Настройка аффинности в исполняемом файле
14.7.2 Изменение аффинностей процессов во время выполнения
14.8 Материалы для дальнейшего исследования
14.8.1 Дополнительное чтение
14.8.2 Упражнения
Резюме
Глава 15. Пакетные планировщики: наведение порядка в хаосе
15.1 Хаос неуправляемой системы
15.2 Как не быть помехой при работе в занятом работой кластере
15.2.1 Макет пакетной системы для занятых кластеров
15.2.2 Как быть вежливым на занятых работой кластерах и сайтах HPC: распространенные любимые мозоли HPC
15.3 Отправка вашего первого пакетного скрипта
15.4 Автоматические перезапуски для длительных заданий
15.5 Указание зависимостей в пакетных скриптах
15.6 Материалы для дальнейшего исследования
15.6.1 Дополнительное чтение
15.6.2 Упражнения
Резюме
Глава 16. Файловые операции для параллельного мира
16.1 Компоненты высокопроизводительной файловой системы
16.2 Стандартные файловые операции: интерфейс между параллельной и последовательной обработкой
16.3 Файловые операции MPI (MPI-IO) для более параллельного мира
16.4 HDF5 как самоописывающий формат для более качественного управления данными
16.5 Другие пакеты программно-информационного обеспечения для параллельных файлов
16.6 Параллельная файловая система: аппаратный интерфейс
16.6.1 Все, что вы хотели знать о настройке параллельного файла, но не знали, как спросить
16.6.2 Общие подсказки, применимые ко всем файловым системам
16.6.3 Подсказки, относящиеся к конкретным файловым системам
16.7 Материалы для дальнейшего исследования
16.7.1 Дополнительное чтение
16.7.2 Упражнения
Резюме
Глава 17. Инструменты и ресурсы для более качественного исходного кода
17.1 Системы версионного контроля: все начинается здесь
17.1.1 Распределенный версионный контроль подходит для более мобильного мира
17.1.2 Централизованный версионный контроль для простоты и безопасности исходного кода
17.2 Таймерные процедуры для отслеживания производительности исходного кода
17.3 Профилировщики: невозможно улучшить то, что не измеряется
17.3.1 Простые тексто-ориентированные профилировщики для повседневного использования
17.3.2 Высокоуровневые профилировщики для быстрого выявления узких мест
17.3.3 Среднеуровневые профилировщики для руководства разработкой приложений
17.3.4 Детализированные профилировщики обеспечивают подробные сведения о производительности оборудования
17.4 Сравнительные тесты и мини-приложения: окно в производительность системы
17.4.1 Сравнительные тесты измеряют характеристики производительности системы
17.4.2 Мини-приложения придают приложению перспективу
17.5 Обнаружение (и исправление) ошибок памяти для устойчивого приложения
17.5.1 Инструмент Valgrind Memcheck: дублер с открытым исходным кодом
17.5.2 Dr. Memory для заболеваний вашей памяти
17.5.3 Коммерческие инструменты памяти для требовательных приложений
17.5.4 Компиляторно-ориентированные инструменты памяти для удобства
17.5.5 Инструменты проверки столбов ограждения обнаруживают несанкционированный доступ к памяти
17.5.6 Инструменты памяти GPU для устойчивых приложений GPU
17.6 Инструменты проверки потоков для определения гоночных условий
17.6.1 Intel® Inspector: инструмент обнаружения гоночных состояний с графическим интерфейсом
17.6.2 Archer: тексто-ориентированный инструмент обнаружения гоночных условий
17.7 Устранители дефектов: отладчики для уничтожения дефектов
17.7.1 Отладчик TotalView широко доступен на веб-сайтах HPC
17.7.2 DDT – еще один отладчик, широко доступный на веб-сайтах HPC
17.7.3 Отладчики Linux: бесплатные альтернативы для ваших локальных потребностей разработки
17.7.4 Отладчики GPU способны помогать устранять дефекты GPU
17.8 Профилирование файловых операций
17.9 Менеджеры пакетов: ваш персональный системный администратор
17.9.1 Менеджеры пакетов для macOS
17.9.2 Менеджеры пакетов для Windows
17.9.3 Менеджер пакетов Spack: менеджер пакетов для высокопроизводительных вычислений
17.10 Modules: загрузка специализированных цепочек инструментов
17.10.1 Модули TCL: изначальная система модулей для загрузки цепочек программных инструментов
17.10.2 Lmod: имплементация альтернативного пакета Modules на основе Lua
17.11 Размышления и упражнения
Резюме
Приложение А. Справочные материалы
Приложение B. Решения упражнений
Приложение C. Глоссарий
Предметный указатель