[МУЗЫКА] [МУЗЫКА] Добрый день, уважаемые слушатели! В предыдущем модуле мы с вами познакомились с шестью базовыми функциями библиотеки MPI, знания которых вам уже достаточно для того, чтобы начать писать собственные параллельные программы. Однако полный список функций библиотеки MPI — он гораздо богаче. Это и функции парного взаимодействия процессов, это функции коллективного взаимодействия процессов, создание пользовательских типов данных и многое другое. В рамках текущего модуля мы с вами более детально познакомимся с функциями обмена сообщениями между отдельными процессами. В операциях данного типа всегда участвуют не более двух процессов, один из которых передающий, а второй — принимающий. Поэтому операции данного типа часто называют функциями типа «точка-точка», или операциями двухточечного обмена. Прием и передача сообщений — это базовый коммуникационный механизм MPI, его использование можно продемонстрировать на следующем примере: данная программа запускается на двух процессорных элементах, в рамках каждого из порожденных процессов объявляется массив a целочисленный, состоящий из десяти элементов типа int. Далее осуществляется инициализация MPI и самоопределение процессов, то есть каждый процесс определяет свой номер в рамках коммуникатора MPI_COMM_WORLD. Эти номера в нашем случае примут значения 0 и 1. Далее программа разбита на две секции: секция, которая будет выполняться процессором с номером 0, и секция, которая будет выполняться процессором с номером 1. Процессор с номером 0 изменяет содержимое целочисленного массива a и передает сообщение, а именно часть измененного массива a, процессору с номером 1, используя для этого функцию MPI_Send. При вызове функции MPI_Send в качестве входных параметров указывается буфер передачи сообщения и атрибуты сообщения. Буфер указывает на то, какие данные мы собираемся передать, а атрибуты необходимы для доставки сообщения адресату. Как мы уже обсуждали, буфер отправки функции MPI_Send однозначно определяется тремя первыми параметрами, а именно: адресом начала буфера отправки, количеством передаваемых элементов и типом передаваемых элементов. В нашем случае буфер отправки представляет собой часть массива a. Передаваемое сообщение будет содержать 5 элементов массива a, начиная с элемента a[0]. Данные пересылаемого сообщения будут типа MPI_INT. Поэтому будет передано 5 подряд последовательно хранящихся элементов массива a, начиная с элемента a[0]. В свою очередь, атрибуты сообщения определяют номер процессора получателя, идентификатор сообщения и коммуникатор. В нашем случае сообщение передается процессу с номером 1, идентификатором сообщения служит число 99, а передача сообщения происходит в рамках коммуникатора MPI_COMM_WORLD. Теперь рассмотрим секцию процесса с номером 1. Процесс с номером 1 принимает сообщения, используя функцию MPI_Recv, и данные записываются в буфер приема. Первые три параметра функции MPI_Recv также определяют буфер приема. Это адрес начала буфера приема, тип передаваемых элементов и количество передаваемых элементов. В нашем случае буфер приема будет представлять собой часть массива a. Принимаемое сообщение будет содержать 10 элементов типа MPI_INT, начиная с элемента массива a[0]. Следующие три параметра необходимы для выбора принимаемого сообщения, то есть они указывают от процесса с каким номером принимать, какой идентификатор должен быть у сообщения и в рамках какого коммуникатора принимается это сообщение. Последний параметр записывает служебную информацию о принятом сообщении. Его мы рассмотрим в следующих лекциях. Далее процессор с номером 1 выводит на экран содержимое массива a. Результатом выполнения данной программы будет следующее сообщение, выданное на экран. Поскольку нулевой процессор передает первому процессу только часть элементов массива a, то только часть элементов массива a на первом процессоре будут изменены, как мы видим на слайде. Этот пример показывает, как должно соотноситься количество передаваемых элементов сообщения с количеством принимаемых элементов. В первую очередь, длина принимаемого сообщения должна быть равна или быть меньше длины буфера приема. Другими словами, буфер приема должен быть в состоянии вместить получаемое сообщение. В противном случае программа прекратит свою работу, указав в качестве ошибки «сообщение обрезано при приеме». Этот случай наглядно продемонстрирован в примере 1. Здесь нулевой процесс посредством функции MPI_Send передает сообщение процессу с номером 1. Это сообщение состоит из пяти элементов типа INT. А первый процесс принимает сообщения посредством функции MPI_Recv, но при приеме указано принять три элемента. В данном случае программа завершит свою работу, выдав сообщение об ошибке. С другой стороны, принимаемое сообщение может быть короче буфера приема. В таком случае изменятся только участки буфера, затронутые сообщением, как это получилось в рассматриваемой нами задаче. Таким образом, мы с вами разобрали функцию приема и отправки сообщения, обсудили список входных и выходных параметров. А в рамках следующей лекции мы с вами рассмотрим функции блокирующего и неблокирующего обмена и рассмотрим, с какого момента можно повторно использовать буфер приема или отправки сообщения. Спасибо за внимание! До свидания!