/* * ex6.c -- пример 6 см.также -- http://www.csa.ru/~il/mpi_tutor * * Создание коммуникатора-дупликата, надежное разделение потоков сообщений: * MPI_Comm_dup, MPI_Comm_free * * Измененный подход к обработке ошибок через * MPI_Abort, MPI_Barrier */ #include #include #define tag1 1 #define tag2 2 #define tag3 1 /* сознательная "ошибка": идентификатор равен 'tag1' */ #define ELEMS(x) (sizeof( x )/sizeof( x[0] )) int main( int argc, char **argv ) { MPI_Comm myComm; int rank, size; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); /* Обработка ошибки "неверное количество запущенных задач" */ if( size != 2 && rank==0 ) { printf( "ERROR: 2 processes required instead of %d, abort.\n", size ); MPI_Abort( MPI_COMM_WORLD, MPI_ERR_OTHER ); } /* Барьер нужен, чтобы в случае ошибки, пока ветвь 0 рапортует * о ней и вызывает MPI_Abort, остальные ветви не смогли приступить * к выполнению содержательной части программы. */ MPI_Barrier( MPI_COMM_WORLD ); /** Общая часть закончена, начинается содержательная часть... **/ /* Создаем еще один коммуникатор - копию MPI_COMM_WORLD */ MPI_Comm_dup( MPI_COMM_WORLD, &myComm ); if( rank == 0 ) /* Ветвь 0 передает */ { static char buf1[] = "Contents of first message"; static char buf2[] = "Contents of second message"; static char buf3[] = "Contents of third message"; /* Обратите внимание: хотя для сообщений выбран один и тот же * идентификатор, описатели области связи разные */ MPI_Send( buf1, ELEMS(buf1), MPI_CHAR, 1, tag1, myComm ); MPI_Send( buf2, ELEMS(buf2), MPI_CHAR, 1, tag2, MPI_COMM_WORLD ); MPI_Send( buf3, ELEMS(buf3), MPI_CHAR, 1, tag3, MPI_COMM_WORLD ); } else /* Ветвь 1 принимает */ { char buf1[100], buf2[100], buf3[100]; MPI_Status st; /* Вызов НЕ перехватит первое сообщение из-за того, что tag1=tag3 */ MPI_Recv( buf3, ELEMS(buf3), MPI_CHAR, 0, tag3, MPI_COMM_WORLD, &st ); /* Вызов НЕ перехватит первое сообщение джокером */ MPI_Recv( buf2, ELEMS(buf2), MPI_CHAR, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &st ); /* Первое сообщение будет успешно принято там, где надо */ MPI_Recv( buf1, ELEMS(buf1), MPI_CHAR, 0, tag1, myComm, &st ); /* Печатаем результаты приема */ printf("Received in buf1 = \'%s\'\n", buf1 ); printf("Received in buf2 = \'%s\'\n", buf2 ); printf("Received in buf3 = \'%s\'\n", buf3 ); } /* rank 1 */ /* Уведомляем MPI, что больше коммуникатором не пользуемся. * После этого myComm будет сброшен в MPI_COMM_NULL (то есть в 0), * а соответствующие ему данные будут помечены на удаление. */ MPI_Comm_free( &myComm ); MPI_Finalize(); }