- •Руководство программиста
- •1. Назначение программы
- •1.1. Назначение
- •1.2. Условия применения
- •2. Характеристика программы
- •2.1. Программа и параллельный алгоритм
- •2.2. Особенности функционального подхода к распараллеливанию
- •2.3. Примеры программ
- •2.3.1. Числа Фибоначчи
- •2.3.3. Рекурсивный обход дерева
- •2.5. Особенности реализации в различных операционных системах
- •2.5.1. OpenTs для Windows
- •2.5.1.1. Платформа Windows Compute Cluster Server
- •2.5.1.2. Инсталлятор
- •2.5.1.3. Набор для разработчика (sdk)
- •2.5.1.4. Интеграция с Visual Studio 2005
- •2.5.1.5. Сборка t-приложений
- •2. Локально в параллельном режиме, используя mpiexec:
- •3. На кластере, используя приложение Cluster Job Submission and Monitoring Console, которое поставляется вместе с Compute Cluster Pack:
- •2.6. Особенности организации параллельных вычислений при помощи т- системы
- •2.7. Программное обеспечение т-системы и дополнительные возможности
- •2.7.2. Архитектура ядра т-системы
- •2.8. Сервисные возможности т-системы
- •2.9. Алгоритм поддержки общей памяти
- •2.9.1. Решения, использованные при построении Суперпамяти
- •2.9.2. Описание архитектуры и программной реализации Суперпамяти
- •2.9.3. Передача значений с узла на узел
- •2.9.4. Алгоритм работы сборщика программного мусора
- •2.9.5. Операции присваивания и «замораживания» неготовых величин
- •2.9.6. Возможное расширение адресного пространства суперпамяти для поддержки распределенных вычислительных сетей
- •2.10. Планирование в OpenTs
- •2.10.1. Постановка задачи
- •2.10.2. Алгоритм планирования
- •Допустим, мы имеем данные t1, t2 и d(t). Рассмотрим эффект от пересылки некоторой задачи с узла 1 на узел 2. Предположим,
- •Где δi зависят от сложности задачи и ее сетевой активности. При этом:
- •2.11. Метапланировщик OpenTs
- •2.12. Поддержка отказоустойчивости исполнения т-приложений
- •2.12.1. Неготовые значения и незавершенные по причине сбоя вычисления
- •2.12.2. Вектор перерождений
- •2.12.3. Вектор посещений
- •2.12.4. Классы повреждений т-функции в случае сбоя
- •3. Обращение к программе
- •3.2. Пример программы, использующей суперпотоки (уровень s)
- •3.3. Использование т-структур и массивов переменного размера
- •3.4. Описание классов реализации системы OpenTs
- •3.4.1. Уровень суперпамяти и суперпотоков
- •3.4.2. Уровень мобильных объектов, мобильных ссылок и мобильных заданий
- •3.4.3. Уровень поддержки т-семантики
- •3.4.4. Сервисные классы
- •3.6. Определение т-контекста во время исполнения программы
- •4. Сообщения
- •4.1. Цветовая схема
- •4.2. Сообщения о фатальных ошибках
- •4.3. Информационные сообщения
- •5. Приложение a. Пример вставки и замены листьев в дереве.
- •6. Приложение b. Использование динамического массива.
2.3. Примеры программ
Для того чтобы ознакомиться с базовыми конструкциями Т-системы и языка T++, рассматриваются два простых примера: числа Фибоначчи и рекурсивный обход древовидной структуры данных.
2.3.1. Числа Фибоначчи
На рис. 1 представлена программа вычисления n-ого числа Фибоначчи. Вычисление намеренно реализовано не самым оптимальным образом — при помощи «прямолинейного» кодирования известного рекурсивного определение для чисел Фибоначчи.
Вызовы Т-функций fib (строки 9, 15) являются новой гранулой параллелизма, готовой к вычислению. Они помещается в очередь, откуда локальные вычислительные процессы- исполнители (работающие на каждом вычислительном узле кластера, в количестве, равном числу процессоров в этом SMP узле) черпают работу сначала для себя, а затем (в случае полной локальной загрузки) и для других свободных вычислительных процессов в кластере. Обращение к неготовым переменным на чтение (за значением) блокирует процесс вычисления функции. Неготовые переменные, таким образом, являются средством синхронизации и посредниками при создании новых узлов редуцируемого вычислительного графа. Существенно различаются ситуации обращения к неготовым переменным на чтение (доступ за значением) и на запись (доступ для присваивания):
#include <stdio.h>
#include <stdlib.h>
tfun int fib (int n) {
return n < 2 ? n : fib(n-1) + fib(n-2);
}
tfun int main (int argc, char *argv[]) {
if (argc != 2) { printf("Usage: fib <n>\n"); return 1; }
int n = atoi(argv[1]);
printf("fib(%d) = %d\n", n, (int)fib(n));
return 0;
}
Рис. 1. Программа вычисления чисел Фибоначчи
При компиляции этой программы конвертером t++ со специальной опцией -auto-c-call достигается скорость вычислений, практически одинаковая с со скоростью C-версии (откомпилированной обычным компилятором без Т-системы) за счет автоматического перехода на вызовы С-версий Т-функций при большой глубине вызовов. Но при этом Т- версия хорошо масштабируется на несколько десятков вычислительных узлов.
Компиляция программы осуществляется при помощи либо конвертера (t++) либо компилятора tg++. В нашем примере используется конвертер:
t++ -o fib fib.tcc
Запуск программы, в общем случае, осуществляется при помощи стандартных средств запуска параллельных приложений, например, в случае SCALI MPI:
mpirun –np 4 ./fib
Возможен также и запуск приложения в режиме монопроцессора, например, при отладке:
./fib
При запуске, консольный вывод приложения содержит статистическую информацию о выполнении программы: общее время исполнения, число запущенных Т-функций и другую. Конвертером Т++ поддерживается компиляция приложения с отладочным выводом, запуск отладочной версии порождает, во время выполнения, вывод информации о создающихся Т-переменных, запуске Т-функций и ожидании неготовых величин.
2.3.2. Краткая характеристика языка Т++
На примере программы вычисления чисел Фибоначчи мы познакомились с языком Т++ — входным языком Т-системы. Язык T++ разработан как синтаксически и семантически гладкое расширение языка C. Под «гладкостью» здесь понимается то, что дополнительные конструкции синтаксически и семантически увязаны с конструкциями основного языка C.
Явные параллельные конструкции, понимаемые в привычном смысле, в языке T++ отсутствуют, например, программист не указывает, какие части программы следует выполнять параллельно. Т-функции указывают прототипы (шаблоны) возможных гранул параллелизма— реально гранулы параллелизма возникают и обрабатываются Т-системой во время работы программы, во время вызовов Т-функций. Указаниями для организации параллельного счета являются элементы расширения синтаксиса и семантики языка, которые наиболее адекватно отражают архитектуру, функциональность и назначение Т-системы, а также зависимости по данным между отдельными счетными гранулами. Ключевые слова языка T++ и используемые специфические функции и макроопределения, свойственные языку T++, перечислены и описаны в документации языка T++. Набор таких ключевых слов невелик, и освоить его не составит труда для любого программиста, привыкшего к написанию программ на языке C++. Основные ключевые слова языка T++, описывающие основные типы данных языка, реализованы как шаблоны, написанные на языке C++, например:
ключевое слово tval реализовано как шаблонный класс TVar<...> языка C++;
ключевое слово tptr реализовано как шаблонный класс TPtr<...> языка C++. Данное ключевое слово употребляется для описания удаленного указателя, то есть указателя, который содержит в себе не только информацию об адресе в памяти, но и номер вычислительного узла кластера, для которого указывается этот адрес;
Параметризованные классы (шаблоны), определяемые Т-системой, можно непосредственно использовать в коде на языке C++, например, если требуется распараллелить программный модуль, реализованный на языке C++.
Имеется возможность последовательного исполнения программ на языке Т++.
Добавленные в язык С расширения выглядят достаточно прозрачными для синтаксиса и семантики языка C. Это позволяет программу на языке T++ разрабатывать и отлаживать без использования Т-системы. Для этого достаточно использовать специальный заголовочный файл txx, который переопределяет (с помощью макроопределений) все ключевые слова, добавленные в язык C. Таким образом Т++ программу можно компилировать обычными компиляторами С, выполнять в последовательном (однопроцессорном) режиме и отлаживать, используя штатные однопроцессорные средства отладки. Данное свойство упрощает первый этап цикла разработки программ, позволяя отлаживать последовательные части реализованного функционального алгоритма в наиболее удобной, привычной для программиста среде.
