57
MPI_Comm cart, subcart;
// создаем коммуникатор с декартовой топологией
int dim[ndims] = {sqrtsize, sqrtsize}, period[ndims] = {true, true};
MPI_Cart_create(MPI_COMM_WORLD, ndims, dim, period, false, &cart);
int coords[ndims], &vcoord = coords[0], &hcoord = coords[1];
MPI_Cart_coords(cart, rank, ndims, coords);
// разбиваем декартов коммуникатор по строкам
int split[ndims] = {false, true};
MPI_Cart_sub(cart, split, &subcart);
// получим группы (они нужны для трансляции рангов)
MPI_Group gcart, gsubcart;
MPI_Comm_group(cart, &gcart);
MPI_Comm_group(subcart, &gsubcart);
// правая матрица (локальная часть)
matrix_type<double> mtx1loc(nloc, nloc);
// ... инициализация правой матрицы
// левая матрица (локальная часть)
matrix_type<double> mtx2loc(nloc, nloc);
// ... инициализация левой матрицы
// матрица - результат умножения (локальная часть)
matrix_type<double> resloc(nloc, nloc);
// выполнение умножения mtx1 на mtx2 слева (res = mtx2 * mtx1)
for (int k = 0; k < sqrtsize; k++)
{
// вычислим ранг процесса-источника для рассылки
// блока левой матрицы среди строки процессов
int src, dst, subroot;
MPI_Cart_shift(cart, 1, hcoord - vcoord - k, &src, &dst);
MPI_Group_translate_ranks(gcart, 1, &src, gsubcart, &subroot);
// разошлем блок левой матрицы всем процессам строки
matrix_type<double> mtx2copy(mtx2loc.vsize(), mtx2loc.hsize());
if (rank == src)
mtx2copy = mtx2loc;
MPI_Bcast(
&mtx2copy(1, 1),
mtx2loc.vsize() * mtx2loc.hsize(), MPI_DOUBLE,
subroot,
subcart);
// перемножим локальные блоки левой и правой матрицы
matrix_type<double> mloc = mtx2copy * mtx1loc;
// сохраним квадратный блок результата
if (k == 0)
resloc = mloc;
else
resloc += mloc;