#ifndef HPC_MPI_MATRIX_HPP #define HPC_MPI_MATRIX_HPP 1 #include #include #include #include #include #include #include #include namespace hpc { namespace mpi { /* construct MPI data type for a row of Matrix A where the extent is adapted such that consecutive rows can be combined even if they overlap */ template class Matrix, Require>> = true> MPI_Datatype get_row_type(const Matrix& A) { MPI_Datatype rowtype; MPI_Type_vector( /* count = */ A.numCols(), /* blocklength = */ 1, /* stride = */ A.incCol(), /* element type = */ get_type(A(0, 0)), /* newly created type = */ &rowtype); /* in case of row-major we are finished */ if (A.incRow() == A.numCols()) { MPI_Type_commit(&rowtype); return rowtype; } /* the extent of the MPI data type does not match the offset of subsequent rows -- this is a problem whenever we want to handle more than one row; to fix this we need to use the resize function which allows us to adapt the extent to A.incRow() */ MPI_Datatype resized_rowtype; MPI_Type_create_resized(rowtype, 0, /* lb remains unchanged */ A.incRow() * sizeof(T), &resized_rowtype); MPI_Type_commit(&resized_rowtype); MPI_Type_free(&rowtype); return resized_rowtype; } /* create MPI data type for matrix A */ template class Matrix, Require>> = true> MPI_Datatype get_type(const Matrix& A) { MPI_Datatype datatype; if (A.incCol() == 1) { MPI_Type_vector( /* count = */ A.numRows(), /* blocklength = */ A.numCols(), /* stride = */ A.incRow(), /* element type = */ get_type(A(0, 0)), /* newly created type = */ &datatype); } else { /* vector of row vectors */ MPI_Datatype rowtype = get_row_type(A); MPI_Type_contiguous(A.numRows(), rowtype, &datatype); MPI_Type_free(&rowtype); } MPI_Type_commit(&datatype); return datatype; } } } // namespaces mpi, hpc #endif // HPC_MPI_MATRIX_H