/* * ex3.c -- пример 3 см.также -- http://www.csa.ru/~il/mpi_tutor * * Функции общего назначения для работы с типами: * MPI_Type_commit, MPI_Type_free, MPI_Type_extent * Создание пользовательских типов данных: * MPI_Type_vector, MPI_Type_hvector * * 1) Быстрая передача решетки: * передаются только те ячейки, у которых обе координаты нечетные * x.x.x * ..... x - выделятся и передаются * x.x.x * ..... . - игнорируются * x.x.x * * 2) Передача с транспонированием: столбцы становятся строками * * Совет: перед тем, как запускать этот пример, * переключите терминал/сессию в режим с максимальным количеством строк. */ #include #include /* количество строк и столбцов в исходной матрице */ #define SIZE 7 /* только для первого примера: * количество строк и столбцов в итоговой матрице */ #define halfSize (SIZE+1)/2 int main( int argc, char **argv ) { int a[ SIZE ][ SIZE ], /* исходная матрица - для обоих примеров */ b[ halfSize ][ halfSize ], /* итоговая матрица для первого примера */ c[ SIZE ][ SIZE ]; /* итоговая матрица для второго примера */ int rank, i, j; MPI_Aint typeExtent; MPI_Datatype /* описатели пользовательских типов */ oneSlice, twoSlice, /* для первого примера */ oneRow, rowByRow; /* для второго примера */ MPI_Status status; /* нужна только для приема, не используется */ /*-----------------* * Инициализация * *-----------------*/ MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); /* Нам нужен только один процесс: он будет и передатчиком, и приемником. * Остальные процессы завершаются немедленно. */ if( rank != 0 ) goto done; /* Генерируем исходную матрицу и печатаем ее */ for( i=0; i Новый тип накрывает РОВНО ОДНУ строку матрицы шаблоном 'x.x.x.x.' */ MPI_Type_vector( halfSize, 1, 2, MPI_INT, &oneSlice ); /* Создаем тип из элементов вида 'x.x.x.x.........' * #1. Количество элементов в новом типе = половине числа строк * #2. Каждый элемент содержит одну ячейку типа 'oneSlice' * #3. Начала элементов отстоят друг от друга через две строки * => Новый тип накрывает матрицу решеткой с нечетными координатами */ MPI_Type_hvector(halfSize, 1, SIZE*2*sizeof(int), oneSlice, &twoSlice ); /* Регистрируем тип 'twoSlice' для использования. * Поскольку тип 'oneSlice' используется только * для порождения других типов, его регистрировать не надо. */ MPI_Type_commit( &twoSlice ); /* На этом подготовительная работа, выполняемая * РОВНО ОДИН РАЗ, завершена. */ /* Посылаем сами себе. * Отправляем одну переменную типа 'twoSlice', * расположенную по адресу матрицы 'a'. * Принимаем поток целых чисел и размещаем его по адресу матрицы 'b' */ MPI_Sendrecv( a, 1, twoSlice, rank, 0, b, halfSize*halfSize, MPI_INT, rank, 0, MPI_COMM_WORLD, &status ); /* Печать принятой подматрицы */ puts("Received sub-matrix:"); for( i=0; i