- •Оглавление
- •Глава 1. Архитектура вычислительных систем 11
- •Глава 2. Реализация параллельных алгоритмов 63
- •Глава 3. Надежность и живучесть вычислительных систем 96
- •Глава 4. Библиотека параллельных программ 120
- •Глава 5. Граф-схемы параллельных алгоритмов 150
- •Глава 6. Исследование информационных граф-схем со скалярными весами для планирования параллельных вычислений 182
- •Глава 7. Исследование информационных граф-схем решаемых задач с векторными весами для планирования параллельных вычислений 204
- •1.Количественные характеристики, применяемые для оценок параметров вычислительных систем
- •Глава 1. Архитектура вычислительных систем
- •Для случая неоднородной системы номинальное быстродействие выразится как
- •Здесь – вероятность выбора j-й операции, , . Для однородной вс её быстродействие по Гибсону выразится соотношением
- •Для неоднородной вс это быстродействие может быть определено, как
- •1.1.1. Вопросы к разделу 1.1.
- •2.Понятие о современных вычислительных системах
- •Пример графа регулярной вычислительной системы представлен на рисунке 1.2.1.
- •Примечание: Для регулярной вычислительной системы
- •2.1. Вопросы к разделу 1.2.
- •3.Структура современных вычислительных систем
- •3.1.Схема обмена с помощью структуры «Общая шина»
- •3.2.Схема обмена с помощью структуры «Линейка»
- •3.3.Вычислительная система, имеющая структуру типа «Кольцо»
- •3.4.Схема обмена с помощью структуры типа «Решётка»
- •1.3.5. Схема обмена с помощью структуры типа «Двумерный тор»
- •3.1.Схема обмена с помощью структуры типа «n-мерный двоичный гиперкуб» или «nD-куб»
- •3.2.Реализация обмена с помощью структуры типа «Обобщенный nD-куб»
- •3.3.Структура вс типа «n-мерный обобщённый тор»
- •3.4.Структура вс с сетью типа «Циркулянт»
- •1.3.10. Вычислительная система «Максимальный обхват»
- •1.3.11. Вычислительные системы со структурой сетей типа «Симметричные графы»
- •На рисунке 1.3.11. Представлена вс с симметричным графом.
- •1.3.12. Вычислительные системы с сетью связей типа «Гомоморфные графы»
- •1.3.13. Вычислительные системы с сетью связей типа «Граф л(n,V,g)»
- •1.3.14. Структура вычислительной системы типа «Бинарное дерево t0(n) глубины n»
- •1.3.15. Структура вычислительной системы типа «Мультидерево глубины n и ширины k t1(n,k)»
- •3.5. Вопросы к разделу 1.3
- •4.Коммуникационные среды вычислительных систем
- •Коммуникационная среда должна удовлетворять следующим требованиям:
- •4.1.Коммуникационная среда на основе масштабируемого когерентного интерфейса sci
- •4.2.Коммуникационная среда на основе технологии Myrinet
- •1.4.3. Краткая характеристика коммуникационной среды QsNet II
- •4.3. Вопросы к разделу 1.4
- •5.Коммутаторы вычислительных систем
- •1.5.1. Типы коммутаторов
- •5.1. Управление коммутаторами
- •5.2. Алгоритмы определения маршрутов
- •5.3. Дедлоки в составных коммутаторах
- •5.4.Вопросы к разделу 1.5
- •6.Процесс функционирования вычислительных систем
- •6.1. Вопросы к разделу 1.6.
- •7.Принципы технической реализации вс
- •1.7.1. Вопросы к разделу 1.7
- •1.8. Архитектурные особенности вс
- •1.8.1. Архитектурные свойства вс
- •1.8.2. Схема обмена информацией между ветвями параллельных алгоритмов
- •7.1.Опыт применения методики крупноблочного распараллеливания сложных задач
- •7.2.Архитектурные аспекты при создании ос вс
- •7.3.Структурные характеристики вс
- •7.4.Классификация структур вс
- •7.5.Вопросы к разделу 1.8.
- •Глава 2. Реализация параллельных алгоритмов
- •2.1. Реализация параллельных алгоритмов
- •2.1.1. Определение параллельного алгоритма
- •7.6.Организация динамического распараллеливания в суперскалярных микропроцессорах
- •2.1.3. Предварительная выборка команд и предсказание переходов
- •7.7.Декодирование команд, переименование ресурсов и диспетчеризация
- •7.8.Исполнение команд
- •2.1.6. Работа с памятью
- •2.1.7. Завершение выполнение команды
- •2.1.8. Направления развития суперскалярной архитектуры
- •7.9.Мультитредовая модель выполнения программы
- •7.10.Аппаратные и программные средства, необходимые для мультитредовой архитектуры
- •2.1.11. Специфика мультитредовых моделей распараллеливания
- •2.1.12. Вопросы к разделу 2.1
- •2.2.Организация распараллеливания на уровне программных модулей
- •2.2.1. Примеры организации вычислений на уровне программных модулей
- •2.2.2. Решение системы линейных уравнений методом Гаусса с помощью вс типов «решётка» и «линейка»
- •2.2.3. Исполнение алгоритма Гаусса на «решётке» n*n вm
- •2.2.4. Исполнение алгоритма Гаусса на «линейке», состоящей из n вм
- •2.2.5. Показатели эффективности параллельных алгоритмов
- •2.2.6. Понятие о сложных задачах
- •2.2.7. Вопросы к разделу 2.2
- •Глава 3. Надежность и живучесть вычислительных систем
- •8.Основные задачи создания отказоустойчивых систем
- •8.1.Вопросы к разделу 3.1
- •9.Классификация типов отказоустойчивости сложных систем и ее критерии
- •9.1.Вопросы к разделу 3.2
- •10.Способы обеспечения отказоустойчивого функционирования вс
- •3.3.1. Диагностическое тестирование вс
- •3.3.3. Способы восстановления отказоустойчивых вс
- •10.1.Вопросы к разделу 3.3
- •3.4. Построение живучих вс на основе экспоненциально- надежностного подхода
- •3.4.1. Показатели надежности вс
- •10.2. Методика расчета показателей надежности вс
- •3.4.3. Живучесть вс
- •3.4.4. Вопросы к разделу 3.4
- •11.Построение живучих вс, работоспособных в расчетном диапазоне кратностей отказов
- •3.6.1. Горячий резерв
- •3.6.2. Репликация
- •3.6.3. Кластеры высокой готовности
- •3.5.1. Вопросы к разделу 3.5
- •3.6. Реализация модели отказоустойчивых систем
- •4.1.2. Принципиальная схема программирования в OpenMp
- •11.2. Описание основных конструкций open mp
- •4.1.4. Способы построения параллельных программ
- •4.1.6. Вопросы к разделу 4.1
- •4.2. Основы построения библиотеки mpi
- •4.2.1. Основные понятия
- •4.2.2. Структура программ в mpi
- •4.2.3. Определение структуры приходящего сообщения
- •4.2.4. Определение базовых характеристик коммуникационной сети
- •11.4.Анализ тупиковых ситуаций при обмене
- •4.2.6. Организация передачи-приёма сообщений без блокировки
- •4.2.7. Реализация отложенных запросов на взаимодействие
- •4.2.8. Сравнительная оценка различных способов обмена данными
- •4.2.9. Использование глобальных операций в mpi
- •4.2.10. Взаимодействие процессов в mpi
- •4.2.11. Вопросы к раделу 4.2
- •Глава 5. Граф-схемы параллельных алгоритмов
- •5.1. Представление параллельных алгоритмов в виде граф-схем
- •5.1.1. Преобразование последовательных алгоритмов в параллельные
- •5.1.2.Использование граф-схем для представления параллельных алгоритмов
- •5.1.3. Вопросы к разделу 5.1
- •5.2.1. Вычисление матриц следования, расширенных матриц следования и матриц следования с транзитивными связями
- •5.2.2. Вопросы к разделу 5.2
- •11.5.Построение матрицы логической несовместимости.
- •5.3.2. Построение матрицы логической несовместимости операторов
- •5.3.3. Вопросы к разделу 5.3
- •5.4.1. Построение множеств взаимно независимых операторов.
- •5.4.2. Вопросы к разделу 5.4
- •Глава 6. Исследование информационных граф-схем со скалярными весами для планирования параллельных вычислений
- •6.1. Численные характеристики информационных граф-схем со скалярными весами
- •6.1.1 Определение ранних и поздних сроков окончания выполнения операторов.
- •11.6.Определение функций плотности загрузки, и минимальной загрузки для информационных граф-схем
- •6.1.3. Вопросы к разделу 6.1
- •6.2.1. Распределение операторов по вм вычислительной системы с общим полем памяти для информационной граф-схемы
- •6.2.2. Распределение операторов по вм вычислительной системы с общим полем памяти для информационно-логической граф-схемы
- •При срабатывании условного оператора «один», дуги 1.1 требуется 10 вм. Время решения задачи составит 22 условные единицы.
- •6.2.3. Распределение операторов по вм вычислительной системы с распределённой памятью для информационной граф-схемы
- •6.2.4. Реализация диаграмм для общепринятых способов обмена данными между вм вычислительной системы с распределённой памятью для информационной граф-схемы
- •6.2.5. Вопросы к разделу 6.2
- •Глава 7. Исследование информационных граф-схем решаемых задач с векторными весами для планирования параллельных вычислений
- •7.1 Информационная граф-схема решаемых задач с векторными весами вершин
- •7.1.1 Понятие об неоднородных системах
- •7.1.2. Основные определения, используемые для неоднородных вс
- •7.1.3. Вопросы к разделу 7.1
- •Литература
4.1.4. Способы построения параллельных программ
На примере простой программы умножения матриц можно увидеть, как использовать OpenMP для создания параллельной программы. Рассмотрим следующий небольшой фрагмент программы умножения двух матриц, используя достаточно простой алгоритм.
for (ii = 0; ii < dim; ii++) {
for (jj = 0; jj < dim; jj++) {
for (kk = 0; kk < dim; kk++) {
array[ii][jj] += array1[ii][kk] * array2[kk][jj];
}
}
}
Обратите внимание, что на каждом уровне вложенности циклов тела циклов могут выполняться независимо друг от друга. Так что создать фрагмент параллельной программы достаточно просто: необходимо вставить прагму #pragma omp parallel for перед самым внешним циклом (циклом по переменной ii). Лучше всего вставить прагму перед самым внешним циклом, так как это даст наибольший выигрыш в производительности. В преобразованном цикле переменные array, array1, array2 и dim являются общими для потоков, а переменные ii, jj и kk являются частными для каждого потока. Приведенный выше фрагмент преобразуется к виду:
#pragma omp parallel for shared(array, array1, array2, dim) private(ii, jj, kk) for (ii = 0; ii < dim; ii++) { for (jj = 0; jj < dim; jj++) { for (kk = 0; kk < dim; kk++) { array[ii][jj] = array1[ii][kk] * array2[kk][jj]; } } }
В качестве другого примера рассмотрим следующий фрагмент кода, предназначенный для вычисления суммы значений f(x) для целых аргументов из интервала 0 <= x < n.
for (ii = 0; ii < n; ii++) {
sum = sum + some_complex_long_fuction(a[ii]);
}
Для построения параллельной программы приведенного выше фрагмента в качестве первого шага можно сделать следующее:
#pragma omp parallel for shared(sum, a, n) private(ii, value)
for (ii = 0; ii < n; ii++) {
value = some_complex_long_fuction(a[ii]);
#pragma omp critical
sum = sum + value;
}
или, что лучше, можно использовать оператор приведения, в результате чего получится
#pragma omp parallel for shared(a, n) private(ii) reduction(+: sum) for (ii = 0; ii < n; ii++) { sum = sum + some_complex_long_fuction(a[ii]); }
Анализируя выше приведенные примеры, можно сделать вывод, что создавать параллельные программы можно несколькими способами. Во-первых, следует определить, поддаётся ли алгоритм распараллеливанию. Если создается новый проект, то можно выбрать алгоритм, который может быть распараллелен. Предварительно очень важно убедиться, что программа выполняется правильно в последовательном режиме. Необходимо также определить временные характеристики при последовательном выполнении, по которым можно будет принять решение о целесообразности распараллеливания.
Скомпилируйте последовательную версию в нескольких режимах оптимизации. Вообще говоря, компилятор может выполнить гораздо более серьезную оптимизацию, чем сам программист.
По мере готовности программы для распараллеливания, можно применить ряд функций и средств Sun Studio, которые помогут достигнуть цели. Они кратко описаны ниже.
Можно попробовать применить ключ автоматического распараллеливания компилятора (-xautopar). Доверив распараллеливание компилятору, программист может получить требуемую программу без каких-либо усилий со своей стороны. Кроме того, автоматический распараллеливатель может помочь определить фрагменты программы, которые можно распараллеливать с помощью прагм OpenMP, и в особенности, которые могут помешать распараллеливанию (например, зависимости между повторениями тела цикла). Комментарии компилятора можно просмотреть, скомпилировав программу с ключом – g, и использовав служебную программу er_src(1) из состава Sun Studio, например, следующим образом:
% cc -g -xautopar -c source.c
% er_src source.o
Одним из наиболее распространенных типов ошибок в программировании с использованием OpenMP являются ошибки в определении области действия переменных, когда область действия переменной указывается неверно, например, переменная определяется как общая (частная), в то время как ее нужно определить как частную (общую). Функция автоопределения области действия переменных в компиляторах Sun Studio освобождает программиста от задачи определения областей действия переменных. Поддерживаются два расширения OpenMP: оператор __auto и оператор default(__auto). Отладчик Sun Studio, dbx, поддерживает работу с потоками и может использоваться для отладки программы, использующей OpenMP. Для отладки программы, использующей OpenMP, следует, во-первых, скомпилировать программу без какой-либо оптимизации, использовав ключи компилятора –xopenmp = noopt -g, затем запустить dbx для отладки полученного исполнимого модуля. С помощью dbx можно устанавливать точки останова внутри области параллельности и выполнять программу в области параллельности в пошаговом режиме, проверять переменные, являющиеся частными для потока, и так далее. Система Sun Studio позволяет производить определение узких мест в программе.
Анализатор производительности Sun Studio можно использовать для разных целей. Это средство можно использовать для определения критических областей в программе, занимающих большую часть времени. Кроме того, это средство предоставляет возможности измерения времени работы и ожидания для функций, что может помочь в определении узких мест в программе, использующей OpenMP.
11.3.Спецификация OpenMP для языков C и C++
Спецификация OpenMP для C и C++, выпущенная на год позже фортранной, содержит в основном аналогичную функциональность.
Необходимо лишь отметить следующие моменты:
1) Вместо специальных комментариев используются директивы компилятора «#pragma omp».
2) Компилятор с поддержкой OpenMP определяет макрос «_OPENMP», который может использоваться для условной компиляции отдельных блоков, характерных для параллельной версии программы.
3) Распараллеливание применяется к for-циклам, для этого используется директива «#pragma omp for». В параллельных циклах запрещается использовать оператор break.
4) Статические (static) переменные, определенные в параллельной области программы, являются общими (shared).
5) Память, выделенная с помощью malloc(), является общей (однако указатель на нее может быть как общим, так и приватным).
6) Типы и функции OpenMP определены во включаемом файле <omp.h>.
7) Кроме обычных, возможны также «вложенные» (nested) замки – вместо логических переменных используются целые числа. Нить, уже захватившая замок, при повторном захвате может увеличить это число.
Пример распараллеливания for-цикла в C:
#pragma omp parallel for private(i)
#pragma omp shared(x, y, n) reduction(+: a, b)
for (i=0; i<n; i++)
{
a = a + x[i];
b = b + y[i];
}
Знать, когда использовать технологию OpenMP, не менее важно, чем уметь с ней работать. Целевая платформа является многопроцессорной или многоядерной. Если приложение полностью использует ресурсы одного ядра или процессора, то, сделав его многопоточным при помощи OpenMP, вы почти наверняка повысите его быстродействие.
Приложение должно быть кроссплатформенным. А так как оно реализовано на основе директив pragma, приложение можно скомпилировать даже при помощи компилятора, не поддерживающего стандарт OpenMP.
Выполнение циклов нужно распараллелить. Весь свой потенциал OpenMP демонстрирует при организации параллельного выполнения циклов. Если в приложении есть длительные циклы без зависимостей, OpenMP – идеальное решение.
Перед выпуском приложения нужно повысить его быстродействие. Так как технология OpenMP не требует переработки архитектуры приложения, она прекрасно подходит для внесения в программу небольших изменений, позволяющих повысить его быстродействие.
Эта технология ориентирована в первую очередь на разработчиков высокопроизводительных вычислительных систем и наиболее эффективна, если программа включает много циклов и работает с разделяемыми массивами данных.
Большинство параллельных циклов будут выполняться быстрее последовательных даже при значительно меньшем числе итераций. Это зависит от объема работы, выполняемой на каждой итерации. При этом важно оценивать производительность ПО, так как само по себе применение OpenMP не гарантирует, что быстродействие вашего кода повысится.
OpenMP-директивы pragma просты в использовании, но не позволяют получать детальные сведения об ошибках. Еще одна ситуация, в которой следует сохранять бдительность, имеет место при использовании потоков Windows вместе с потоками OpenMP. Потоки OpenMP создаются на основе потоков Windows, поэтому они прекрасно работают в одном процессе. Увы, OpenMP ничего не знает о потоках Windows, созданных другими модулями. Из этого вытекают две проблемы: во-первых, исполняющая среда OpenMP не ведет учет других потоков Windows, а во-вторых, методы синхронизации OpenMP не синхронизируют потоки Windows, потому что они не входят в группы потоков.
