коммунистические вычисления ALEK SILVERSTONE Спецвыпуск: Хакер, номер #065, стр. 065-070-5 MPI_Pack(add_data_p, add_count, add_type, buf_p, buf_size, buf_pos_p, comm); add_data_p — указатель на данные, которые нужно упаковать. add_count — количество ячеек памяти. add_type — MPI-тип этих ячеек. buf_p — указатель на буфер, куда упаковываются данные. buf_size — размер буфера. buf_pos_p — указатель на текущую позицию в buf. Не забудь в начале записать туда 0 ! После выполнения функции значение изменяется. comm — коммуникатор. Размер буфера для упаковки можно узнать с помощью функции MPI_Pack_size. В качестве параметров этой функции передаются число ячеек памяти, их тип, коммуникатор и адрес, по которому записывается размер необходимого буфера. Сначала значение по этому адресу нужно сделать равным нулю, затем — последовательно вызывать MPI_Pack_size (значения суммируются автоматически). На принимающей стороне последовательность действий такая: «подсмотреть» размер пакета, подсчитать размер буфера для распаковки, выделить память и распаковать туда пакет. Первое выполняет функция MPI_Probe. Параметры — ранг отправителя, идентификатор сообщения, коммуникатор и указатель на структуру MPI_Status, в которую будут записаны параметры сообщения. Стандарт MPI гарантирует, что вызов MPI_Recv, следующий за MPI_Probe и имеющий те же значения ранга, идентификатора и коммуникатора, получит именно то сообщение, параметры которого были «подсмотрены» первой функцией. Размер буфера можно подсчитать функцией MPI_Get_count — ей передаются указатель на наш MPI_Status, тип данных (в этом случае MPI_BYTE) и на указатель, по которому будет записан необходимый размер буфера. Распаковка вызывается функцией MPI_Unpack, которой передаются те же параметры, что и Pack'у, только в другом порядке. На врезке можешь посмотреть код, демонстрирующий использование этих функций. рассмотрим простейшую программу на C++ — она показана на врезке. Сначала мы инициализируем библиотеку MPICH и получаем ранг и общее количество процессов в глобальном коммуникаторе. Затем выводим приветственное сообщение и останавливаемся на барьере до тех пор, пока все потоки не дойдут до этого места. Функция flush вызывается для принудительно сброса содержимого экранного буфера на консоль. Если это действие не осуществится, то, может случиться, один процесс начнет выводить сообщение в середине вывода другого. Далее выполняется одна из двух веток (выбор определенной ветки зависит от ранга процесса). Первая ветка выполняется нулевым процессом. Сначала она рассылает всем значение своего ранга (то есть ноль), затем принимает любые (MPI_ANY_TAG) сообщения от любых (MPI_ANY_SOURCE) процессов и рапортует о получении. Вторая ветка работает на всех остальных процессах. Сначала она получает сообщение от процесса 0 с идентификатором 111, затем отсылает этому процессу свой ранг, притом идентификатор сообщения равен 222. |