Your SlideShare is downloading. ×
0
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
20090721 hpc exercise2
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

20090721 hpc exercise2

813

Published on

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
813
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • MPI – стандарт системы параллельного программирования, основанный на модели обмена сообщениями. Версия стандарта 1.1 описывает следующие виды взаимодействия параллельных процессов : Парные обмены – группа операций приема-передачи сообщений от одного процесса другому. Коллективные операции – к ним относятся операции, задействующие все или ряд выделенных процессов. Операции над группами и коммуникационными контекстами – операции, связанные с порождением и управлением группами процессов и коммуникаторами Топологии процессов – в этом разделе стандарта описаны поддерживаемые MPI виды процессных топологий и операции работы с ними Привязки к языкам – пожалуй, самый большой раздел стандарта, описывающий синтаксис вызовов библиотечных функций MPI из программ на C и Fortran . Основными реализациями являются MPICH и MSMPI
  • Необходимо понимать, что MPI описывает семантику взаимодействия процессов только через СВОИ функции. Если программист пользуется другими инструментами – прямой доступ к памяти и сети, межпроцессные обмены и каналы – он делает это на свой страх и риск  Также, одной из основных целей создания MPI как стандарта было разработать кросс-платформенное решение. Ни одна операция MPI не является платформозависимой, лишь конкретная реализация стандарта будет вносить свои коррективы прозрачно для программиста. В стандарт не входят описания инструментов отладки и поддержки управления задачами, хотя бы потому, что такие инструменты являются платформозависимыми. Поставщики реализаций MPI могут поставлять такие инструменты самостоятельно.
  • Локальной называется операция, не вызывающая взаимодействия процессов. Используя такую операцию мы можем быть уверены, что никакой обмен информацией между процессами не производится. Нелокальная операция МОЖЕТ при необходимости вызывать взаимодействие процессов. Необходимо отметить, что одна и та же операция в зависимости от условий ее выполнения может быть как локальной, так и нелокальной – см. пример MPI_Send с буферизацией и без Коллективная операция – это операция, которая ОБЯЗАТЕЛЬНО должна вызываться всеми процессами группы, в рамках которой она производится. Если некоторый процесс группы опрацию не вызывает, это считается ошибкой хода выполнения.
  • Блокирующие функции подразумевают выход из них только после полного окончания операции, т.е. вызывающий процесс блокируется, пока операция не будет завершена. Для функции посылки сообщения это означает, что все пересылаемые данные помещены в буфер (для разных реализаций MPI это может быть либо какой-то промежуточный системный буфер, либо непосредственно буфер получателя). Для функции приема сообщения блокируется выполнение других операций, пока все данные из буфера не будут помещены в адресное пространство принимающего процесса. Ресурсы, указанные в ее параметрах, можно безопасно использовать повторно (например, данные переданы или скопированы в системный буфер). Неблокирующие функции подразумевают совмещение операций обмена с другими операциями, поэтому неблокирующие функции передачи и приема по сути дела являются функциями инициализации соответствующих операций. Для опроса завершенности операции (и завершения) вводятся дополнительные функции.
  • Префикс S (synchronous) - означает синхронный режим передачи данных. Операция передачи данных заканчивается только тогда, когда заканчивается прием данных. Функция нелокальная. Префикс B (buffered) - означает буферизованный режим передачи данных. В адресном пространстве передающего процесса с помощью специальной функции создается буфер обмена, который используется в операциях обмена. Операция посылки заканчивается, когда данные помещены в этот буфер. Функция имеет локальный характер. Префикс R (ready) - согласованный или подготовленный режим передачи данных. Операция передачи данных начинается только тогда, когда принимающий процессор выставил признак готовности приема данных, инициировав операцию приема. Функция нелокальная. Префикс I (immediate) - относится к неблокирующим операциям. Все функции передачи и приема сообщений могут использоваться в любой комбинации друг с другом. Функции передачи, находящиеся в одном столбце, имеют совершенно одинаковый синтаксис и отличаются только внутренней реализацией. Поэтому в дальнейшем будем рассматривать только стандартный режим, который в обязательном порядке поддерживают все реализации MPI.
  • С момента своего запуска любая правильно написанная MPI программа должна пройти следущие этапы : Запуск – программа запускается планировщиком. Инициализация среды – на этом этапе в среде MPi устанавливаются необходимые параметры и порождаются внутренние объекты. Также именно здесь создается глобальный и локальный коммуникаторы MPI_COMM_WORLD и MPI_COMM_SELF Непосредственно вычисления – выполнение кода, написанного программистом. Завершение среды MPI – освобождение ресурсов, занятых средой MPI . Повторная инициализация среды невозможна. Выгрузка – освобождение ресурсов, занятых процессами, их закрытие.
  • Любая MPI-программа (приложение) должна начинаться с вызова функции инициализации MPI: функции MPI_Init. В результате выполнения этой функции создается группа процессов, в которую помещаются все процессы приложения, и создается область связи, описываемая предопределенным всеобщим коммуникатором MPI_COMM_WORLD. Эта область связи объединяет все процессы-приложения. Процессы в группе упорядочены и пронумерованы от 0 до groupsize-1, где groupsize равно числу процессов в группе. Кроме этого, создается предопределенный коммуникатор MPI_COMM_SELF, описывающий свою область связи для каждого отдельного процесса. До вызова MPI_INIT любые вызовы функций MPI, кроме MPI_Initialized , будут заканчиваться ошибкой. В программах на C каждому процессу при инициализации передаются аргументы функции main, полученные из командной строки. В программах на языке FORTRAN параметр IERROR является выходным и возвращает код ошибки.
  • Если какой-либо процесс закончит свою работу до вызова MPI_Finalize (например, аварийно) , MPI- программа завершится с ошибкой. После вызова MPI_Finalize невозможен вызов ни одной функции библиотеки MPI
  • Рассмотрим структуру MPI приложения: mpi.h – заголовочный файл, в котором определены все функции MPI argv – аргументы командной строки argc – их количество Пример - simplest
  • После выполнения этой функции в переменную flag будет сохранено значение 1 ( True) , если среда выполнения MPI инициализирована (то есть, был успешный вызов MPI_Init()) , либо 0, в противном случае.
  • MPI _Comm_size возвращает в переменную size количество процессов в коммуникаторе comm. Подставляя в эту функцию всеобщий коммуникатор MPI_COMM_WORLD мы можем получить количество процессов, на которых запущена программа.
  • MPI_Comm_rank возвращает номер процесса (то есть, ранг), вызвавшего ее. Номера процессов всегда лежат на интервале 0 … < размер группы > – 1 и, естетсвенно, уникальны для каждой группы. При этом ранг процесса в коммуникаторе MPI_COMM_WORLD можно считать абсолютным рангом процесса. Ранги процесса в других (созданных программистом, об этом в MPI advanced techniques) будут относительными.
  • Сообщения в MPI передаются как пакеты, содержащие данные вместе с информацией их описывающей. Наличие информации, например, о реальном размере передаваемых данных может оказаться весьма полезной в некоторых случаях. При отправке сообщения мы должны указать следующие параметры : Собственно, массив данных, которые мы хотим передать. Размер массива передаваемых данных – система выполнения должна точно знать, сколько данных мы передаем. О типах данных ниже. Процесс-получатель сообщения – при парных обменах вполне естественный параметр. Тег данных – это специальная метка, позволяющая в программе отличать одни данные от других. Тег задается программистом произвольно. При приеме сообщения также необходимо указывать буфер данных, в котором данные принятого сообщения будут сохранены, размер этого буфера, тег принимаемых данных и процесс-отправитель сообщения. При вызове команды получения данных система будет искать сообщение с запрошенными тегом и процессом-отправителем. Если будет найдено сообщение с указанными значениями, оно будет принято и сохранено. Иначе система будет ждать, пока нужное сообщение появится.
  • Сообщения в MPI передаются как пакеты, содержащие данные вместе с информацией их описывающей. Наличие информации, например, о реальном размере передаваемых данных может оказаться весьма полезной в некоторых случаях. При отправке сообщения мы должны указать следующие параметры : Собственно, массив данных, которые мы хотим передать. Размер массива передаваемых данных – система выполнения должна точно знать, сколько данных мы передаем. О типах данных ниже. Процесс-получатель сообщения – при парных обменах вполне естественный параметр. Тег данных – это специальная метка, позволяющая в программе отличать одни данные от других. Тег задается программистом произвольно. При приеме сообщения также необходимо указывать буфер данных, в котором данные принятого сообщения будут сохранены, размер этого буфера, тег принимаемых данных и процесс-отправитель сообщения. При вызове команды получения данных система будет искать сообщение с запрошенными тегом и процессом-отправителем. Если будет найдено сообщение с указанными значениями, оно будет принято и сохранено. Иначе система будет ждать, пока нужное сообщение появится.
  • Функция MPI_Send производит отпарвку сообщения из буфера buf процессу с рангом dest в коммуникаторе comm . Далее будут рассмотрены различные режимы работы MPI_Send . Необходимо отметить, что по усмотрению системы выполнения MPI , функция MPI_Send может сохранять передаваемые данные в буфер и возвращать управление в программу, а может блокировать ее выполнение до появления запроса на прием сообщения, посылаемого функцией MPI_Recv .
  • MPI_Recv выполняет прием сообщения от процесса source . Выполнение программы будет заблокировано до того момента, как собщение будет полностью сохранено в буфере buf . В параметре status будет сохранен статус сообщения : его тег, его полный размер (он может быть и больше заданного параметром MPI_Recv ) и процесс-отправитель.
  • В таблице приведены типы данных MPI для языков C и Fortran. MPI содержит специальные функции, позволяющие конструировать собственные типы данных – об этом в MPI Advanced techniques .
  • MS-MPI входит в состав HPC Pack 2008 . Также скачать SDK можно со страницы http://go.microsoft.com/fwlink/?linkID= 127031 Допустим, что SDK установлен в папку is C:Program FilesMicrosoft HPC Pack 2008 SDK. При выборе платформы Win32 необходимо указать директории для подключаемых и библиотечных файлов. Для этого необходимо в Visual Studio выбрать в меню Обратите внимание, что эти действия необходимо проделать для каждого типа проекта: Win32 Debug, Win32 Release, x64 Debug, и x64 Release.
  • Изменим алгоритм изменения контрастности изображения для работы на кластере. Необходимо чтобы MPI приложение выполняло следующий алгоритм: 1. Распределение частей матрицы изображения равномерно между вычислительными узлами 2. Каждый узел выполняет преобразования над полученной частью матрицы 3. Результирующую матрица формировалась из данных полученных от каждого узла. Для начала создадим приложение в котором главный узел рассылает по вычислительным узлам части матрицы, а потом они Посылают эти части матирицы на главный узел, который собирает их в одну матрицу. Проверку исходной матрицы и полученной будет производить с помощью программы WinDiff
  • Для всех узлов кроме первого вычисление контрастности пикселей начинается со первой строки матрицы и заканчивается предпоследней ( rows-1 ) строкой матрицы изображения. Первый узел начинает вычисления со 2-й строки т.к. для него нет 0-й (пересылаемой). Тоже самое можно сказать и о последнем узле, вычисления которого останавливаются на предпоследней строке.
  • Как вы помните, для реализации алгоритма изменения контрастности, для всех узлов кроме первого и последнего требуются дополнительные строки.
  • Обратите внимание на окончание цикла for , где отображается количество измененных пикселей, и если нет измененных пикселей, вычисления останавливаются: } } cout << " (diffs until convergence: " << diffs << ")" << endl; converged = (diffs == 0); В последовательной версии алгоритма переменная diffs объявлена как локальная. В связи с тем, что вычисление контрастности происходит на множестве узлов, переменная diffs должна быть объявлена как глобальная , таким образом чтобы узлы могли передавать значения локальной переменной diffs главному узлу. Главный узел вычисляет сумму, и если она равна 0, то вычисления прекращаются, в ином случае отправляет новое значение вычислительным узлам
  • Transcript

    • 1. Реализация параллельного алгоритма с использованием MPI
    • 2. Содержание <ul><li>Основы MPI </li></ul><ul><li>Настройка проекта Visual Studio 200 8 </li></ul><ul><li>Основные функции MPI </li></ul><ul><li>Блокирующие функции обмена сообщениями. Типы данных </li></ul><ul><li>Выполнение упражнения </li></ul>
    • 3. Стандарт MPI
    • 4. Стандарт MPI <ul><li>Что включено в стандарт MPI? </li></ul><ul><ul><li>Парные обмены ( point-to-point communications) </li></ul></ul><ul><ul><li>Коллективные операции ( collective operations) </li></ul></ul><ul><ul><li>Операции над группами процессов (process groups) </li></ul></ul><ul><ul><li>Операции над коммуникационными контекстами (communication contexts) </li></ul></ul><ul><ul><li>Топологии процессов ( process topologies) </li></ul></ul><ul><ul><li>Привязки к языкам C и Fortran 77 (language binding) </li></ul></ul>
    • 5. Стандарт MPI <ul><li>Что в стандарт не входит ? </li></ul><ul><ul><li>Способы взаимодействия процессов, отличные от использования средств библиотеки MPI (общая память и т.д.) </li></ul></ul><ul><ul><li>Операции, требующие использования особенностей программно-аппаратной среды </li></ul></ul><ul><ul><li>Описание способов отладки </li></ul></ul><ul><ul><li>Явная поддержка многопоточной обработки данных </li></ul></ul><ul><ul><li>Поддержка управления задачами </li></ul></ul><ul><ul><li>Функции ввода-вывода </li></ul></ul>
    • 6. Термины MPI
    • 7. Термины MPI <ul><li>Локальная операция – процедура, не требующая взаимодействия с другими процессами. </li></ul><ul><li>Нелокальная операция – процедура, выполнение которой может потребовать выполнения действий на других процессах. Такая процедура МОЖЕТ потребовать взаимодействия с другими процессами. </li></ul><ul><li>Коллективная операция – процедура, которая должная быть выполнена всеми процессами группы. </li></ul>
    • 8. Термины MPI <ul><li>Блокирующая операция – подразумевает выход из нее только после полного окончания операции, т.е. вызывающий процесс блокируется, пока операция не будет завершена </li></ul><ul><li>Неблокирующая операция - подразумевает совмещение операций обмена с другими операциями.Как правило, ее выполнение происходит в параллельном потоке и не вызывающий процесс не блокируется. </li></ul>
    • 9. Термины MPI Режимы выполнения С блокировкой Без блокировки Стандартная посылка MPI_Send MPI_Isend Синхронная посылка MPI_Ssend MPI_Issend Буферизованная посылка MPI_Bsend MPI_Ibsend Согласованная посылка MPI_Rsend MPI_Irsend Прием информации MPI_Recv MPI_Irecv
    • 10. Термины MPI <ul><li>Коммуникатор – контекст взаимодействия процессов с помощью функций MPI . За коммуникатором закрепляется некоторая группа процессов. Также возможно определение виртуальных топологий для упрощения структуризации обменов в рамках коммуникатора. Процессы в группе (и, как следствие, коммуникаторе) нумеруются от 0 до (< размер_группы > - 1) </li></ul><ul><li>MPI_COMM_WORLD – предопределенная в библиотеке MPI константа, представляющая коммуникатор, включающий все процессы запущенной MPI- программы. </li></ul><ul><li>MPI_COMM_SELF – предопределенная в библиотеке MPI константа, представляющая коммуникатор, включающий только текущий процесс. </li></ul>
    • 11. Термины MPI <ul><li>С : </li></ul><ul><ul><li>все функции начинаются с префикса MPI_ </li></ul></ul><ul><li>int MPI_Init(int * argc , char ** argv ); </li></ul><ul><li>int MPI_Finalize(void); </li></ul><ul><li>int MPI_Initialized(int * flag ); </li></ul><ul><ul><li>все функции имеют тип int и возвращают либо значение MPI_SUCCESS (в случае нормального завершения), либо код, соответствующий произошедшей ошибке </li></ul></ul>
    • 12. Термины MPI <ul><li>При описании функций и их параметров будем использовать следующие обозначения : </li></ul><ul><ul><li>Данные, помеченные [IN] , считаются входными для функции (процедуры), то есть, используются внутри нее, но не изменяются. </li></ul></ul><ul><ul><li>Данные, помеченные [OUT] , считаются выходными и могут быть изменены. </li></ul></ul><ul><ul><li>Данные, помеченные [INOUT] , используются внутри функции и могут быть изменены. </li></ul></ul>
    • 13. Структура MPI- программы
    • 14. Структура MPI- программы <ul><li>Основные этапы жизненного цикла MPI -программы : </li></ul><ul><li>Запуск </li></ul><ul><li>Инициализация среды выполнения MPI </li></ul><ul><li>Вычисления </li></ul><ul><li>Завершение среды выполнения MPI </li></ul><ul><li>Выгрузка </li></ul>
    • 15. Структура MPI- программы <ul><li>MPI_Init(argc, argv) </li></ul><ul><ul><li>[INOUT] argc – количество параметров командной строки запуска программы </li></ul></ul><ul><ul><li>[INOUT] argv – параметры командной строки, используемые для передачи параметров в программу </li></ul></ul><ul><ul><li>C: int MPI_Init(int *argc, char ***argv) </li></ul></ul><ul><li>Функция MPI_Init создает группу процессов, в которой содержатся все процессы MPI- программы, и соответствующий этой группе коммуникатор MPI_COMM_WORLD . </li></ul><ul><li>Может быть вызвана только один раз, попытка повторной инициализации завершится ошибкой. </li></ul>
    • 16. Структура MPI- программы <ul><li>MPI_Finalize() </li></ul><ul><ul><li>Без параметров </li></ul></ul><ul><li>C: int MPI_Finalize(void ) </li></ul><ul><li>Функция MPI_Finalize освобождает ресурсы, занятые средой выполнения MPI . </li></ul>
    • 17. Структура MPI- программы <ul><li>#include <stdio.h> </li></ul><ul><li>#include <mpi.h> </li></ul><ul><li>int main(int argc, char* argv[]) </li></ul><ul><li>{ </li></ul><ul><li>int ierr; </li></ul><ul><li>ierr = MPI_Init(&argc, &argv); // Инициализация среды MPI </li></ul><ul><li>if (ierr != MPI_SUCCESS) </li></ul><ul><li>return ierr; </li></ul><ul><li>printf(&quot;Hello world &quot;); // Полезная работа </li></ul><ul><li>MPI_Finalize(); // Завершение среды MPI </li></ul><ul><li>} </li></ul>
    • 18. Основные функции MPI
    • 19. Основные функции MPI <ul><li>MPI_Initialized(flag) </li></ul><ul><ul><li>[OUT] flag – возвращает 0, если среда выполнения MPI не была еще инициализирована </li></ul></ul><ul><li>C: int MPI_Initialized(int *flag ) </li></ul><ul><li>Функция MPI_Initialized позволяет выяснить, была ли среда выполнения MPI уже инициализирована. </li></ul>
    • 20. Основные функции MPI <ul><li>MPI_Comm_size(comm, size) </li></ul><ul><ul><li>[IN] comm – коммуникатор, размер которого хотим определить. </li></ul></ul><ul><ul><li>[OUT] size – количество процессов в коммуникаторе comm </li></ul></ul><ul><li>C: int MPI_Comm_size(MPI_Comm comm, int *size) </li></ul><ul><li>Функция MPI_Comm_size возвращает в переменную size количество процессов в коммуникаторе comm . </li></ul>
    • 21. Основные функции MPI <ul><li>MPI_Comm_rank(comm, rank) </li></ul><ul><ul><li>[IN] comm – коммуникатор, относительно которого мы хотим определить ранг текущего процесса. </li></ul></ul><ul><ul><li>[OUT] rank – ранг текущего процесса в коммуникаторе comm </li></ul></ul><ul><li>C: int MPI_Comm_rank(MPI_Comm comm, int *rank) </li></ul><ul><li>Функция MPI_Comm_rank возвращает в переменную rank ранг текущего процесса в коммуникаторе comm . </li></ul><ul><li>В различных коммуникаторах ранги одного и того же процесса могут быть различны, но обязательно уникальны в рамках каждого коммуникатора. </li></ul>
    • 22. Блокирующие функции обмена сообщениями
    • 23. Блокирующие функции обмена сообщениями <ul><li>Сообщения – данные, передаваемые между процессами, вместе с дополнительной информацией – их описанием </li></ul><ul><li>Сообщения помечаются тегом – произвольно задаваемым программистом целым числом </li></ul><ul><li>Тег и дополнительная информация передаются в оболочке сообщения </li></ul><ul><li>Каждой операции отправки сообщения должна соответствовать операция приема. </li></ul>
    • 24. Блокирующие функции обмена сообщениями <ul><li>Оболочка сообщения содержит : </li></ul><ul><ul><li>Ранг процесса-источника сообщения </li></ul></ul><ul><ul><li>Ранг процесса-получателя сообщения </li></ul></ul><ul><ul><li>Количество передаваемых в сообщении данных </li></ul></ul><ul><ul><li>Тег сообщения </li></ul></ul><ul><ul><li>Коммуникатор, в рамках которого происходит отправка </li></ul></ul>
    • 25. Блокирующие функции обмена сообщениями <ul><li>MPI_Send(buf, count, datatype, dest, tag, comm) </li></ul><ul><ul><li>[IN] buf – указатель на буфер отправляемых данных </li></ul></ul><ul><ul><li>[IN] count – количество данных типа datatype в буфере buf </li></ul></ul><ul><ul><li>[IN] datatype – тип отправляемых данных </li></ul></ul><ul><ul><li>[IN] dest – ранг процесса, которому отсылаем данные </li></ul></ul><ul><ul><li>[IN] tag – тэг отсылаемых данных </li></ul></ul><ul><ul><li>[IN] comm – коммуникатор </li></ul></ul><ul><li>С : MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, </li></ul><ul><li>int tag, MPI_Comm comm) </li></ul><ul><li>Функция MPI_Send отсылает сообщение из буфера buf процессу с рангом dest . </li></ul>
    • 26. Блокирующие функции обмена сообщениями <ul><li>MPI_Recv(buf, count, datatype, source, tag, comm, status) </li></ul><ul><ul><li>[OUT] buf – указатель на буфер, в который будут сохранены полученные данные </li></ul></ul><ul><ul><li>[IN] count – количество принимаемых данных типа datatype </li></ul></ul><ul><ul><li>[IN] datatype – тип принимаемых данных </li></ul></ul><ul><ul><li>[IN] source – ранг процесса, от которого принимаем данные, или MPI_ANY_SOURCE </li></ul></ul><ul><ul><li>[IN] tag – тэг принимаемых данных или MPI_ANY_TAG </li></ul></ul><ul><ul><li>[IN] comm – коммуникатор </li></ul></ul><ul><ul><li>[OUT] status – статус полученного сообщения </li></ul></ul><ul><li>С : MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) </li></ul><ul><li>Функция MPI_Recv принимает сообщение от процесса с рангом source . В случае, если ранг не известен или не важен, можно указать значение MPI_ANY_SOURCE . Если неизвестен или неважен тэг сообщения, можно указать значение MPI_ANY_TAG . </li></ul>
    • 27. Типы данных MPI C MPI_CHAR signed char MPI_SHORT signed short int MPI_INT signed int MPI_LONG signed long int MPI_UNSIGNED_CHAR unsigned char MPI_UNSIGNED_SHORT unsigned short int MPI_UNSIGNED unsigned int MPI_UNSIGNED_LONG unsigned long int MPI_FLOAT float MPI_DOUBLE double MPI_LONG_DOUBLE long double
    • 28. Настройка проекта в Visual Studio 200 8
    • 29. Настройка проекта в Visual Studio 200 8 <ul><li>1) Project -> Project Properties-> CC++-> General – > Additional Include Directories : </li></ul><ul><li>затем нажмите на икону и выберите папку:   </li></ul><ul><li> C:Program FilesMicrosoft HPC Pack 2008 SDKInclude </li></ul><ul><li>2) Project -> Project Properties-> Linker -> General -> Additional Library Directories : </li></ul><ul><li>C:Program FilesMicrosoft HPC Pack 2008 SDKLibi386  </li></ul><ul><li>Project -> Project Properties-> Linker -> Input: </li></ul><ul><li>msmpi.lib Ws2_32.lib </li></ul><ul><li>Для платформы x64, и введите папки :  </li></ul><ul><li>C:Program FilesMicrosoft HPC Pack 2008 SDKInclude </li></ul><ul><li>C:Program FilesMicrosoft HPC Pack 2008 SDKLibamd64 </li></ul>
    • 30. Настройка проекта в Visual Studio 200 8
    • 31. Настройка проекта в Visual Studio 200 8
    • 32. Настройка проекта в Visual Studio 200 8
    • 33. Настройка проекта в Visual Studio 200 8
    • 34. Выполнение упражнения
    • 35. Выполнение упражнения Master Worker Worker Master Master Send / Recv Worker
    • 36. Выполнение упражения <ul><li>Запустите проект в папке Exercises3 MPIMPIContrastStretch . Настройте проект для создания MPI приложений как сказано выше. Выберите архитектуру процессора (Win32 или x64) . Добавьте в файл “app.h” строку #include <mpi.h> . </li></ul><ul><li>В самом начале главной функции добавьте вызовы функций MPI_Init, MPI_Comm_size, MPI_Comm_rank, и gethostname . Для более простого способа отладки объявите связанные с ними переменные как глобальные. Например : </li></ul><ul><li>int myRank; </li></ul><ul><li>int numProcs; </li></ul><ul><li>char host[256]; </li></ul><ul><li>int main (int argc, char *argv[]) </li></ul><ul><li>{ </li></ul><ul><li>MPI_Init(&argc, &argv); </li></ul><ul><li>MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myRank); </li></ul><ul><li>gethostname(host, sizeof(host)/sizeof(host[0])); </li></ul><ul><li>… </li></ul><ul><li>MPI_Finalize(); </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
    • 37. Выполнение упражнения <ul><li>2. C оздайте тип данных MPI_PIXEL_T , добавив вызов функции CreateMPIPixelDatatype после вызова MPI_Init . Новый тип MPI данных назовем MPI_PIXEL_T : </li></ul><ul><li>… </li></ul><ul><li>gethostname(host,sizeof(host)/sizeof(host[0])); </li></ul><ul><li>MPI_Datatype MPI_PIXEL_T = CreateMPIPixelDatatype (); </li></ul><ul><li>Для его уничтожения необходимо перед вызовом функции MPI_Finalize все процессы должны вызвать функцию MPI_Type_free : </li></ul><ul><li>… </li></ul><ul><li>MPI_Type_free (&MPI_PIXEL_T); </li></ul><ul><li>MPI_Finalize(); </li></ul><ul><li>return 0; </li></ul>
    • 38. Выполнение упражнения <ul><li>Найдите в файле место, где происходит вызов ContrastStretch и закомментируйте его. добавьте ниже: </li></ul><ul><li>PIXEL_T **chunk = NULL; </li></ul><ul><li>int myrows = 0; </li></ul><ul><li>int mycols = 0; </li></ul><ul><li>  // разделение матрицы на части </li></ul><ul><li>chunk = DistributeImage (image, rows, cols, myrows, mycols, MPI_PIXEL_T); </li></ul><ul><li>assert(chunk != NULL); </li></ul><ul><li>assert(rows > 0); assert(cols > 0); </li></ul><ul><li>assert(myrows > 0); assert(mycols > 0); </li></ul><ul><li>// chunk = ContrastStretch ( chunk , myrows , mycols , steps, stepby, MPI_PIXEL_T);  </li></ul><ul><li>// собирание матрицы </li></ul><ul><li>image = CollectImage (image, rows, cols, chunk , myrows, mycols, MPI_PIXEL_T); </li></ul>
    • 39. Выполнение упражнения <ul><li>Добавьте в проект файлы Distribute.cpp и Collect.cpp. Добавьте в файл Distribute.cpp функцию DistributeImage для распределения частей матрицы между вычислительными узлами : </li></ul><ul><li>#include &quot;app.h” </li></ul><ul><li>#include &quot;mpi.h&quot; </li></ul><ul><li>PIXEL_T **DistributeImage(PIXEL_T **image, int &rows, int &cols, int &myrows, int &mycols, MPI_Datatype MPI_PIXEL_T) </li></ul><ul><li>{ </li></ul><ul><li>return NULL; </li></ul><ul><li>} </li></ul><ul><li>добавьте в файл Collect.cpp функцию CollectImage для сбора частей матрицы в единую матрицу. : </li></ul><ul><li>#include &quot;app.h” </li></ul><ul><li>#include &quot;mpi.h&quot; </li></ul><ul><li>PIXEL_T **CollectImage(PIXEL_T **image, int rows, int cols, PIXEL_T **chunk, int myrows, int mycols, MPI_Datatype MPI_PIXEL_T) </li></ul><ul><li>{ </li></ul><ul><li>return NULL; </li></ul><ul><li>}  </li></ul>
    • 40. Выполнение упражнения <ul><li>Добавьте в файл “app.h” определения функций : </li></ul><ul><li>  </li></ul><ul><li>PIXEL_T **DistributeImage(PIXEL_T **image, int &rows, int &cols, int &myrows, int &mycols, MPI_Datatype MPI_PIXEL_T); </li></ul><ul><li>PIXEL_T **CollectImage(PIXEL_T **image, int rows, int cols, PIXEL_T **chunk, int myrows, int mycols, MPI_Datatype MPI_PIXEL_T); </li></ul><ul><li>Также в файле “app.h” необходимо объявить внешними ( external ) переменные : </li></ul><ul><li>extern int myRank; </li></ul><ul><li>extern int numProcs; </li></ul><ul><li>extern char host[256]; </li></ul>
    • 41. Выполнение упражения <ul><li>6. В файле Main.cpp добавим код, для того чтобы ввод и вывод файлов осуществлялся только главным узлом. Находим строку где выводится &quot;** Reading bitmap from '&quot; и добавляем выше и ниже: </li></ul><ul><li>double time = 0.0; </li></ul><ul><li>if (myRank == 0) </li></ul><ul><li>{ </li></ul><ul><li>cout << &quot;** Reading bitmap from '&quot; << infile << &quot;'...&quot; << endl; </li></ul><ul><li>image = ReadBitmapFile(infile, bitmapFileHeader, bitmapInfoHeader, rows, cols); </li></ul><ul><li>if (image == NULL) </li></ul><ul><li>{ </li></ul><ul><li>cout << endl; </li></ul><ul><li>cout << &quot;** Failed to open image file, halting...&quot; << endl; </li></ul><ul><li> MPI_Abort(MPI_COMM_WORLD, 1); </li></ul><ul><li>} </li></ul><ul><li>cout << &quot;** Bitmap size is &quot; << rows << &quot; rows, &quot; << cols << &quot; cols, &quot; << rows*cols << &quot; pixels...&quot; << endl; </li></ul><ul><li> cout << endl; </li></ul><ul><li>startTime = clock(); </li></ul><ul><li>} </li></ul><ul><li>//image = ContrastStretch(image, rows, cols, steps, stepby); </li></ul>
    • 42. Выполнение упражнения <ul><li>7. Изменим функцию DistributeImage : </li></ul><ul><li>PIXEL_T **chunk = NULL; </li></ul><ul><li>int tag = 0; </li></ul><ul><li>int params[2] = {0, 0}; </li></ul><ul><li>cout << myRank << &quot; (&quot; << host << &quot;): Distributing image...&quot; << endl; </li></ul><ul><li>if ( myRank == 0 ) // выполняется главным узлом : </li></ul><ul><li>{ </li></ul><ul><li>int rowsPerProc = rows / numProcs; </li></ul><ul><li>int leftOverRows = rows % numProcs; </li></ul><ul><li>params[0] = rows; </li></ul><ul><li>params[1] = cols; </li></ul><ul><li>for (int dest=1; dest < numProcs; dest++) // послание каждому процессу размера матрицы </li></ul><ul><li>MPI_Send (params, sizeof(params)/sizeof(params[0]), MPI_INT, dest, tag, MPI_COMM_WORLD); </li></ul><ul><li>for (int dest=1; dest < numProcs; dest++) // послание части матрицы </li></ul><ul><li>MPI_Send (image[leftOverRows + dest*rowsPerProc], rowsPerProc*cols, MPI_PIXEL_T, dest, tag, MPI_COMM_WORLD); </li></ul><ul><li>myrows = rowsPerProc + leftOverRows; </li></ul><ul><li>mycols = cols; </li></ul><ul><li>chunk = New2dMatrix<PIXEL_T>(myrows+2, mycols); // почему на две строки // больше? Смотри функцию изменения контрастности </li></ul><ul><li>memcpy_s(chunk[1], myrows*mycols*sizeof(PIXEL_T), image[0], myrows*mycols*sizeof(PIXEL_T)); </li></ul><ul><li>} </li></ul><ul><li>  </li></ul>
    • 43. Выполнение упражнения <ul><li>else // выполняется вычислительными узлами </li></ul><ul><li>{ </li></ul><ul><li>MPI_Status status; </li></ul><ul><li>MPI_Recv (params, sizeof(params)/sizeof(params[0]), MPI_INT, 0 /*master*/, tag, MPI_COMM_WORLD, &status); </li></ul><ul><li>rows = params[0]; </li></ul><ul><li>cols = params[1]; </li></ul><ul><li>myrows = rows / numProcs; // размер части матрицы </li></ul><ul><li>mycols = cols; </li></ul><ul><li>  </li></ul><ul><li>chunk = New2dMatrix<PIXEL_T>(myrows+2, mycols); // почему на две строки // больше? Смотри функцию изменения контрастности </li></ul><ul><li>MPI_Recv (chunk[1], myrows*mycols, MPI_PIXEL_T, 0 /*master*/, tag, MPI_COMM_WORLD, &status); </li></ul><ul><li>} </li></ul><ul><li>return chunk; </li></ul>
    • 44. Выполнение упражнения <ul><li>8. Изменим функцию CollectImage : </li></ul><ul><li>assert(chunk != NULL); </li></ul><ul><li>assert(rows > 0); </li></ul><ul><li>assert(cols > 0); </li></ul><ul><li>assert(myrows > 0); </li></ul><ul><li>assert(mycols > 0); </li></ul><ul><li>int tag = 0; </li></ul><ul><li>cout << myRank << &quot; (&quot; << host << &quot;): Collecting image...&quot; << endl; </li></ul><ul><li>if (myRank > 0) // вычислительные узлы </li></ul><ul><li>{ </li></ul><ul><li>int dest = 0; // to master </li></ul><ul><li>MPI_Send(chunk[1], myrows*mycols, MPI_PIXEL_T, dest, tag, MPI_COMM_WORLD); </li></ul><ul><li>} </li></ul>
    • 45. <ul><li>else // главный вычислительный узел </li></ul><ul><li>{ </li></ul><ul><li> assert(image != NULL); </li></ul><ul><li> MPI_Status status; </li></ul><ul><ul><li>memcpy_s(image[0], myrows*mycols*sizeof(PIXEL_T), chunk[1], myrows*mycols*sizeof(PIXEL_T)); </li></ul></ul><ul><ul><li>int rowsPerProc = rows / numProcs; </li></ul></ul><ul><li> int leftOverRows = rows % numProcs; </li></ul><ul><li> // получение данных от узлов </li></ul><ul><li> for (int src=1; src < numProcs; src++) </li></ul><ul><li>MPI_Recv(image[leftOverRows + src*rowsPerProc], rowsPerProc*cols, MPI_PIXEL_T, src, tag, MPI_COMM_WORLD, &status); </li></ul><ul><li>} </li></ul><ul><li>Delete2dMatrix<PIXEL_T>(chunk); </li></ul><ul><li>return image; </li></ul>
    • 46. Выполнение упражнения <ul><li>Скомпилируйте приложение, скопируйте изображение в папку с EXE файлом и запустите приложение. С помощью программы WinDiff сравните полученные изображения. </li></ul>
    • 47. 9 . В файле “Main. cpp” уберите комментарии для строки chunk = ContrastStretch(chunk, myrows, mycols, steps, stepby, MPI_PIXEL_T); Измените определение функций ContrastStretch в файл “app.h” : PIXEL_T **ContrastStretch(PIXEL_T **image, int rows, int cols, int steps, int stepby, MPI_Datatype MPI_PIXEL_T ); Откройте файл ContrastStretch.cpp и измените код в соответствии с PIXEL_T **ContrastStretch(PIXEL_T **image, int rows, int cols, int steps, int stepby, MPI_Datatype MPI_PIXEL_T ) { cout << myRank << &quot; (&quot; << host << &quot;): Processing &quot; << rows << &quot;rows,&quot; << cols << &quot; cols...&quot; << endl; PIXEL_T **image2 = New2dMatrix<PIXEL_T>( rows+2 , cols); MPI_Status status; int tag = 0; // Обратите внимание на два дополнительных строки Выполнение упражнения
    • 48. Выполнение упражнения <ul><li>int firstRow = 1; // это справедливо для всех узлов кроме главного </li></ul><ul><li>int lastRow = rows; </li></ul><ul><li>if (myRank == 0) // главный узел начинает вычисления со второй строки </li></ul><ul><li>firstRow = 2; </li></ul><ul><li>  </li></ul><ul><li>if (myRank == numProcs-1) // последний узел не вычисляет значения для // последней строки </li></ul><ul><li>lastRow = rows-1; </li></ul><ul><li>  bool converged = false; </li></ul>
    • 49. Выполнение упражнения <ul><li>1 0 . Для добавления возможности обмена строками необходимо добавить код в самом начале цикла </li></ul><ul><li>while в файле ContrastStretch.cpp : </li></ul><ul><li>cout << myRank << &quot; (&quot; << host << &quot;): ** Step &quot; << step << &quot;...&quot; << endl; </li></ul><ul><li>if (myRank < numProcs-1) // все посылают «вниз» последнюю ( строку кроме последнего узла ): </li></ul><ul><li> MPI_Send(image[lastRow], cols, MPI_PIXEL_T, myRank+1, tag, MPI_COMM_WORLD); </li></ul><ul><li>if (myRank > 0) // все получают строку кроме первого узла </li></ul><ul><li>MPI_Recv(image[firstRow-1], cols, MPI_PIXEL_T, myRank-1, tag, MPI_COMM_WORLD, &status); </li></ul><ul><li>if (myRank > 0) // все посылают вверх первую строку ( кроме // первого узла ): </li></ul><ul><li>MPI_Send (image[1], cols, MPI_PIXEL_T, myRank-1, 0 /*tag*/, MPI_COMM_WORLD); </li></ul><ul><li>if (myRank < numProcs-1) // все получают первую строку (кроме последнего узла </li></ul><ul><li>MPI_Recv (image[rows+1], cols, MPI_PIXEL_T, myRank+1, 0 /*tag*/, MPI_COMM_WORLD, &status); </li></ul>0 1 2 3
    • 50. Выполнение упражнения <ul><li>1 1 . Изменение цикла for для вычисления переменной diffs : </li></ul><ul><li>if (myRank > 0) // вычислительные узлы : </li></ul><ul><li>{ </li></ul><ul><li>MPI_Send(&diffs, 1, MPI_LONG_LONG, 0 /*master*/, 0 /*tag*/, MPI_COMM_WORLD); </li></ul><ul><li>MPI_Recv(&diffs, 1, MPI_LONG_LONG, 0 /*master*/, 0 /*tag*/, MPI_COMM_WORLD, &status); </li></ul><ul><li>} </li></ul>
    • 51. Выполнение упражнения <ul><li>else // главный узел : </li></ul><ul><li>{ </li></ul><ul><li>long long temp; </li></ul><ul><li>for (int src=1; src < numProcs; src++) // получение значений от все вычислительных // узлов : </li></ul><ul><li>{ </li></ul><ul><li>MPI_Recv(&temp, 1, MPI_LONG_LONG, MPI_ANY_SOURCE, 0 /*tag*/, MPI_COMM_WORLD, &status); </li></ul><ul><li>diffs += temp; // суммирование </li></ul><ul><li>} </li></ul><ul><li>for (int dest=1; dest < numProcs; dest++) // отправка вычислительным узлам // нового значения </li></ul><ul><li>MPI_Send(&diffs, 1, MPI_LONG_LONG, dest, 0 /*tag*/, MPI_COMM_WORLD); </li></ul><ul><li>} </li></ul><ul><li>cout << &quot; (diffs until convergence: &quot; << diffs << &quot;)&quot; << endl; </li></ul>
    • 52. Выполнение упражнения <ul><li>12. Обновление циклов копирования матрицы: </li></ul><ul><li>for ( int row = firstRow; row <= lastRow; row++ ) </li></ul><ul><li>for (int col = 1; col < cols-1; col++) </li></ul><ul><li>image[row][col] = image2[row][col]; </li></ul><ul><li>13. И в цикле while </li></ul><ul><li>diffs = 0; </li></ul><ul><li>for (int row = firstRow; row < lastRow; row++) </li></ul><ul><li>{ </li></ul><ul><li>for (int col = 1; col < cols-1; col++) </li></ul><ul><li>{ </li></ul>
    • 53. <ul><li>Скомпилируйте проект и запустите локальной машине </li></ul><ul><li>mpiexec –n 4 MPIApp.exe </li></ul><ul><li>Запишите полученные значения. </li></ul>Выполнение упражнения
    • 54. Выполнение упражнения <ul><li>Скомпилируйте приложение для выполнения на процессоре x64 и скопируйте его вместе с изображением в своем папку на кластере </li></ul><ul><li>Для выполнения MPI- приложения на кластере запустите Job Manager, выберите адрес кластера: HN.PRACTICUM ( 193.232.2.150, <username>: <userpassword>,CLUSTER) </li></ul><ul><li>Добавьте новое задание, указав в командной строке </li></ul><ul><li>mpiexec.exe MPIContrastStretch.exe Sunset.bmp out.bmp 10 10 </li></ul><ul><li>Добавьте в качестве настроек: </li></ul><ul><ul><li>napps <username> </li></ul></ul><ul><ul><li>napps <username>out.txt </li></ul></ul><ul><ul><li>napps <username>err.txt </li></ul></ul>
    • 55. Выполнение упражнения
    • 56. Заключение
    • 57. © 2008 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.

    ×