gpu-direct: make it optional and have fallback solution with device-host explicit transfers - #389
gpu-direct: make it optional and have fallback solution with device-host explicit transfers#389svalat wants to merge 33 commits into
Conversation
…e IdefixCommArrayXD<> to handle the no gpu-direct transfers.
…ginal function names
…h idefix::MPI_ API.
…ers all time for validation purpose
…nd a solution for the NO GPU DIRECT case
… solve the Axis issue
…sing #if WITH_MPI when MPI is disabled
…ccessing a GPU buffer on CPU
… cmake one) : Persistent, Blocking, NonBlocking
…PU_DIRECT and forcing copy in any case for validation
…copy in some tests
1e989f8 to
5431e11
Compare
04913f8 to
f24de7d
Compare
001c28a to
e5b4522
Compare
…FF in related error messages
e5b4522 to
43d4040
Compare
c3991ca to
a29cbd1
Compare
glesur
left a comment
There was a problem hiding this comment.
a few relatively minor things.
What is unclear at this stage is whether we want to accept all possible input data for MPI function, and not just the ones involving IdefixCommArray?
|
|
||
| #include "idefix.hpp" | ||
|
|
||
| namespace idefix { |
There was a problem hiding this comment.
| namespace idefix { | |
| namespace idfx { |
| IdefixArray2D<real> sbEyL; | ||
| IdefixArray2D<real> sbEyR; | ||
| IdefixArray2D<real> sbEyRL; | ||
| idefix::IdefixCommArray2D<real> sbEyL; |
There was a problem hiding this comment.
name space should be idfx:: (like cout, and other global functionalities), or idfxMPI:: (to highlight this is our own implementation)
| #endif | ||
| #if defined(KOKKKOS_ENABLE_CUDA) || defined(KOKKOS_ENABLE_HIP) | ||
| errmsg << "You can look on Idefix cmake option -DIdefix_MPI_GPU_DIRECT=OFF to not" | ||
| "use it (will be slower)." << std::endl; |
There was a problem hiding this comment.
| "use it (will be slower)." << std::endl; | |
| MPI_SAFE_CALL(MPI_File_set_view(fvtk, this->offset, MPI_FLOAT, this->nodeView, | ||
| "native", MPI_INFO_NULL)); | ||
| MPI_SAFE_CALL(MPI_File_write_all(fvtk, node_coord.data(), size_int, | ||
| MPI_SAFE_CALL(idefix::MPI_File_write_all(fvtk, node_coord, size_int, |
There was a problem hiding this comment.
cette réécriture n'est pas utile car node_coord est déjà sur l'hote
| const double allowedImbalance = 20.0; | ||
| std::vector<double> computeLogPerCore(idfx::psize); | ||
| MPI_Gather(&computeLastLog, 1, MPI_DOUBLE, computeLogPerCore.data(), 1, MPI_DOUBLE, 0, | ||
| idefix::MPI_Gather(&computeLastLog, 1, MPI_DOUBLE, computeLogPerCore, 1, MPI_DOUBLE, 0, |
There was a problem hiding this comment.
comprends pas: computeLogPerCore est un std::vector, pas un IdefixArray
| MPI_Recv(np_tot.data(), 3, MPI_INT, rank, 011, MPI_COMM_WORLD, &status); | ||
| MPI_Recv(beg.data(), 3, MPI_INT, rank, 012, MPI_COMM_WORLD, &status); | ||
| MPI_Recv(gbeg.data(), 3, MPI_INT, rank, 013, MPI_COMM_WORLD, &status); | ||
| idefix::MPI_Recv(np_int, 3, MPI_INT, rank, 010, MPI_COMM_WORLD, &status); |
There was a problem hiding this comment.
tout ces tableaux sont des vecteurs sur l'hote, je ne comprends même pas comment ça peut marcher (mais cette routine n'est probablement pas testée)
| * CPU / GPU transfers if the array in on GPU and WITH_MPI_GPU_DIRECT is disabled. | ||
| */ | ||
| template <class T, size_t U> | ||
| int MPI_Send(const std::array<T, U> & buf, int count, MPI_Datatype datatype, |
There was a problem hiding this comment.
pas sur de comprendre l'intéret de cette fonction. Tout encapsuler dans ton API, même pour des fonctions qui n'utilisent pas le GPU aware?
Co-authored-by: Geoffroy Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
Handle when there is no-gpu-direct
The patch mostly wrap the MPI interface to make the transfers manually between the host & device when GPU direct is not available.
In order to avoid allocating an host buffer for every transfers, the
IdefixArrayXDclasses has been extended asIdefixCommArrayXDwhich contains the standard array on device, and optionally (if GPU direct is disabled and if running on GPU) a host buffer to make the communications.In order to apply in the code, all the MPI communication calls (
MPI_Send,MPI_Recv,MPI_Start....) need to be replaced by theidefix::MPI_*corresponding frunctions which expect anIdefixCommArrayas parameter.It means that we should not continue to use
.data()to feed the MPI calls (the compiler will complain for theidefix::MPI_*functions).When the wrapper is called it ensure to sync the communication buffer in & out during the communication process so it is transparent for the calling code.
One care
You should not use directly the
IdefixCommArrayXDin a GPU loop (get a compiler warning in case due to host array in use). This is way the patch uses the.deviceView()to get it casted in a friendly way for the GPU.Note: in case you still keep it that way, it should not be a problem appart the warning in the compilation output because the host array will not be used in the kernel because not accessible (private).
Note: this semantic is only used if we communicate with the buffer, all the rest of the code using standard
IdefixArrayis not concerned.Case of persitent comms
For the persistent comms and async comms, an new
idefix::MPI_Request_XDhas been defined to carry the information on how to sync the communication buffer with its device counter part when required. Again if you useidefix::MPI_*just follow the compiler which will force you to type correctly usingidefix::MPI_Request_XDinstead ofMPI_Request.New CMake flags :
Idefix_MPI_GPU_DIRECT: Enable the fallback imlpementation at compile time (will apply only if at runtime we cannot GPU direct and if we run on GPU.Variable marked as advanced (not seen by default in
ccmake) :Idefix_MPI_GPU_FORCE_COPY: For validation purpose, force the copy in any situation (even on CPU). It should come in conjunition withIdefix_MPI_GPU_DIRECTto have an effect.Idefix_MPI_MODE: To select a compile time via cmake which communication mode to use. Can bePersistent,Blocking,NonBlocking.Validation
In order to validate the implementation in any condition, we can :
Idefix_MPI_GPU_DIRECT.Idefix_MPI_GPU_FORCE_COPY.This is done on the test suite by using the
-mpiGpuForceCopyoption.It can be played in conjuntion with the
-mpiModeoption which can be either :Persistent,NonBlocking,BLockingto validate the various paths.Validation in github actions
The test suite has been extended to test automatically those combinations on the test :
MHD/AxisFluxTube.When having GPU direct
in this case, the
IdefixCommArrayGpuDirectimplementation is used, which is just an empty stub which just does nothing.Questions
MPI_waitallwith multiple comms, I start all the host-device transfers asynchronously and usingKokkos::fence(). I can also avoid it to get simpler code as we have max 2 comms at this location.MPI_*API the same inside theidefix::namespace, we can also name them allMPI_View_to clearly separate the concept. To be discussed what is best.Mpi::CheckConfig()so it uses the copies when not having GPU Direct, is it what we want ?TODO