Goal: Learn how MPI communication is differentiated with CoDiPack and MeDiPack.
Prerequisite: Tutorial 2 - Reverse mode AD
Full code:
#include <codi.hpp>
#include <medi/medi.hpp>
#include <iostream>
using namespace medi;
#include "codi/tools/mpi/codiMpiTypes.hpp"
MpiTypes* mpiTypes;
int main(int nargs, char** args) {
AMPI_Init(&nargs, &args);
mpiTypes = new MpiTypes();
int rank;
int size;
AMPI_Comm_rank(AMPI_COMM_WORLD, &rank);
AMPI_Comm_size(AMPI_COMM_WORLD, &size);
if(size != 2) {
std::cout << "Please start the tutorial with two processes." << std::endl;
} else {
tape.setActive();
if( 0 == rank ) {
tape.registerInput(a);
AMPI_Send(&a, 1, mpiTypes->MPI_TYPE, 1, 42, AMPI_COMM_WORLD);
} else {
AMPI_Recv(&a, 1, mpiTypes->MPI_TYPE, 0, 42, AMPI_COMM_WORLD, AMPI_STATUS_IGNORE);
tape.registerOutput(a);
}
tape.setPassive();
tape.evaluate();
if(0 == rank) {
std::cout <<
"Adjoint of 'a' on rank 0 is: " << a.
getGradient() << std::endl;
}
}
delete mpiTypes;
AMPI_Finalize();
}
#include <medi/medi.cpp>
The differentiation of MPI communication is done via the MeDiPack library (https://scicomp.rptu.de/software/medi). As the example shows all 'MPI_*" routines and functions need to be replaced with the MeDiPack wrapper functions 'AMPI_*'. Otherwise the MPI functions can be used as usual. The only difference is, that the CoDiPack MPI Datatype needs to be used in all communications where CoDiPack types are involved.
If different CoDiPack types are used (e.g. codi::RealReverse and codi::RealReverseIndex), then for each one a CoDiPack MPI Datatype needs to be created.