Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
fec3e60
gpu-direct: handle communications when GPU DIRECT is not there.
svalat Jul 8, 2026
7967a1b
gpu-direct: Implement extensions of MPI API using views and provde th…
svalat Jul 9, 2026
a15c690
gpu-direct: use the MPI view semantic in EMF, axis and exganger
svalat Jul 9, 2026
4742f74
gpu-direct: rename the API to use a namespace and fallback on the ori…
svalat Jul 9, 2026
2af6af6
gpu-direct: fix some extra parts of idefix using MPI
svalat Jul 9, 2026
f38f106
gpu-direct: wrap all the internal MPI_.+ using .data() internally wit…
svalat Jul 10, 2026
7b89da6
gpu-direct: Add a macro to activate to validate by forcing the transf…
svalat Jul 10, 2026
9b58b1c
gpu-direct: fix an issue in MPI_Gather
svalat Jul 10, 2026
75a4c33
gpu-direct: Fix some compilation warnings with CUDA
svalat Jul 10, 2026
433c9c1
gpu-direct: fix mistake in lazy-init, should be done on all entry points
svalat Jul 10, 2026
17e0c76
gpu-direct: Ooops, no cannot lazy init due to the copy semantic
svalat Jul 10, 2026
411866f
gpu-direct: try to avoid the warning in normal way to run, need to fi…
svalat Jul 10, 2026
4a5b620
gpu-direct: Cleanup the way to switch the class ON/OFF by using a sin…
svalat Jul 10, 2026
afa7a4e
gpu-direct: Opps wrong name in option declaration
svalat Jul 10, 2026
03e0f40
gpu-direct: remove a useless scafolding
svalat Jul 10, 2026
76d46ff
gpu-direct: try to implement the copy/move constructor & operator= to…
svalat Jul 10, 2026
aab2e8a
gpu-direct: solve most of the compiler warnings when compiling with CUDA
svalat Jul 10, 2026
61b78f8
gpu-direct: Fix build of test/HD/KHI due to cyclic includes + fix mis…
svalat Aug 14, 2026
2e23ff7
gpu-direct: Fix pyidefix issues by adding the missing MPI wrappers
svalat Aug 14, 2026
7382ba1
gpu-direct: Fix a build issue due to assert variable names in debug mode
svalat Aug 14, 2026
bf3c87f
gpu-direct: fix an issue coming from the previous refactoring about a…
svalat Aug 14, 2026
9ab9f27
gpu-direct: Fix issue with test utils/dumpImage due to missing include
svalat Aug 14, 2026
3d9b17d
test: Add the possibility to test the MPI modes via test options (and…
svalat Aug 17, 2026
15c59bc
gpu-direct: fix none building case in exchanger about MPI_NON_BLOCKIN…
svalat Aug 17, 2026
5834964
gpu-direct: add -mpiGpuForceCopy on test script to run by disabling G…
svalat Aug 17, 2026
643e0c4
gpu-direct: Add testing of the NO_GPU_DIRECT feature by forceing the …
svalat Aug 17, 2026
5431e11
gpu-direct: remove the display of the MPI MODE status in the output o…
svalat Aug 18, 2026
93e5794
Merge branch 'develop' into feature/no-gpu-direct-support
svalat Aug 18, 2026
f24de7d
gpu-direct: fix the build issues with Intel compiler.
svalat Aug 19, 2026
f6bf6e2
gpu-direct: fix nvcc warning about host function used in device one
svalat Aug 19, 2026
43d4040
gpu-direct: Update the doc and inform about -DIdefix_MPI_GPU_DIRECT=O…
svalat Aug 20, 2026
a29cbd1
gpu-direct: fix pre-commit issue
svalat Aug 20, 2026
7b21d3d
Apply suggestions from code review
svalat Aug 26, 2026
d8c52b3
gpu-direct: fix PR remarks : typos in comments + namespace idefix => …
svalat Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ option(Idefix_DEBUG "Enable Idefix debug features (makes the code very slow)" OF
option(Idefix_RUNTIME_CHECKS "Enable runtime sanity checks" OFF)
option(Idefix_WERROR "Treat compiler warnings as errors" OFF)
option(Idefix_PYTHON "Enable python bindings (requires pybind11)" OFF)
option(Idefix_MPI_GPU_DIRECT "Enable usage of GPU direct to avoid CPU-GPU copies for MPI messages." ON)
option(Idefix_MPI_GPU_FORCE_COPY "When GPU_DIRECT is disabled, force using transfers for validation purpose." OFF)
mark_as_advanced(Idefix_MPI_GPU_FORCE_TRANSFERS)
set(Idefix_PROBLEM_DIR "${CMAKE_BINARY_DIR}" CACHE STRING "Problem directory to build for.")
set(Idefix_CXX_FLAGS "" CACHE STRING "Additional compiler/linker flag")
set(Idefix_DEFS "definitions.hpp" CACHE FILEPATH "Problem definition header file")
Expand All @@ -35,6 +38,10 @@ set_property(CACHE Idefix_PRECISION PROPERTY STRINGS Double Single)
set(Idefix_LOOP_PATTERN "Default" CACHE STRING "Loop pattern for idefix_for")
set_property(CACHE Idefix_LOOP_PATTERN PROPERTY STRINGS Default SIMD Range MDRange TeamPolicy TeamPolicyInnerVector)

set(Idefix_MPI_MODE "Persistent" CACHE STRING "MPI communication mode to use.")
set_property(CACHE Idefix_MPI_MODE PROPERTY STRINGS Persistent Blocking NonBlocking)
mark_as_advanced(Idefix_MPI_MODE)

# load git revision tools
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(GetGitRevisionDescription)
Expand Down Expand Up @@ -104,6 +111,10 @@ if(Idefix_MPI)
add_subdirectory(src/mpi)
endif()

if (Idefix_MPI_GPU_DIRECT)
add_compile_definitions("WITH_MPI_GPU_DIRECT")
endif()

if(Idefix_HDF5)
add_compile_definitions("WITH_HDF5")
if(Idefix_MPI)
Expand Down Expand Up @@ -227,6 +238,20 @@ if(${Idefix_PRECISION} STREQUAL "Single")
add_compile_definitions("SINGLE_PRECISION")
endif()

# MPI mode
if(${Idefix_MPI_MODE} STREQUAL "Persistent")
add_compile_definitions("COMMUNICATION_MODE_PERSISTENT")
elseif(${Idefix_MPI_MODE} STREQUAL "NonBlocking")
add_compile_definitions("COMMUNICATION_MODE_NON_BLOCKING")
else(NOT ${Idefix_MPI_MODE} STREQUAL "Blocking")
message(ERROR "Unknown MPI communication mode : Idefix_MPI_MODE=${Idefix_MPI_MODE}")
endif()

# GPU direct disabled and force transfers
if (${Idefix_MPI_GPU_FORCE_COPY})
add_compile_definitions("WITH_GPU_FORCE_COPY")
endif()

target_include_directories(idefix PUBLIC
"${Idefix_PROBLEM_DIR_ABS}"
)
Expand Down Expand Up @@ -264,6 +289,7 @@ endif()
message(STATUS " MPI: ${Idefix_MPI}")
message(STATUS " HDF5: ${Idefix_HDF5}")
message(STATUS " Python: ${Idefix_PYTHON}")
message(STATUS " GPU direct: ${Idefix_MPI_GPU_DIRECT}")
message(STATUS " Reconstruction: ${Idefix_RECONSTRUCTION}")
message(STATUS " Precision: ${Idefix_PRECISION}")
message(STATUS " Version: ${Idefix_VERSION}")
Expand Down
3 changes: 3 additions & 0 deletions doc/source/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ I have a complex setup, and have written some functions in separate .cpp files.
I want to run on the GPUs of xxx machine, how do I proceed?
Check the examples in :ref:`setupExamples`

I don't have a CUDA or HIP aware MPI with GPU DIRECT support, how I can run *Idefix* ?
You can look at the compile option `-DIdefix_MPI_GPU_DIRECT=OFF` in :ref:`makefile` to disable GPU DIRECT usage. Note that this will decrease performances.

Compilation
-----------

Expand Down
6 changes: 6 additions & 0 deletions doc/source/reference/makefile.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _makefile:

Code configuration with Cmake
=============================

Expand Down Expand Up @@ -33,6 +35,10 @@ Several options can be enabled from the command line (or are accessible with ``c
``-D Idefix_MPI=ON``
Enable MPI parallelisation. Requires an MPI library. When used in conjonction with CUDA (Nvidia GPUs), a CUDA-aware MPI library is required by *Idefix*.

``-D Idefix_MPI_GPU_DIRECT=OFF``
Disable the usage of MPI GPU direct for inter-process communication. In this case it uses a copy between GPU and GPU before and after making communications.
It is usefull if your MPI is not GPU-aware. Note that this option decreases performances.

``-D Idefix_DEFS=foo.hpp``
Specify a particular filename to be used in place of the default problem file ``definitions.hpp``

Expand Down
21 changes: 21 additions & 0 deletions pytools/idfx_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,20 @@ def __init__(self, current_test_file, name=""):

parser.add_argument("-mpi", help="Enable MPI", action="store_true")

parser.add_argument(
"-mpiMode",
default="Persistent",
choices=["Default", "Persistent", "NonBlocking", "Blocking"],
help="MPI communication mode to use (Default)",
type=str,
)

parser.add_argument(
"-mpiGpuForceCopy",
action="store_true",
help="Disable MPI GPU direct and force memory transfers for validation purpose.",
)

parser.add_argument(
"-all",
help="Do all test suite (otherwise, just do the test with the current configuration)",
Expand Down Expand Up @@ -268,6 +282,13 @@ def _genCmakeCommand(self, definitionFile=""):
else:
comm.append("-DIdefix_MPI=OFF")

if self.mpiMode != "Default":
comm.append(f"-DIdefix_MPI_MODE={self.mpiMode}")

if self.mpiGpuForceCopy:
comm.append("-DIdefix_MPI_GPU_DIRECT=OFF")
comm.append("-DIdefix_MPI_GPU_FORCE_COPY=ON")

if self.reconstruction == 2:
comm.append("-DIdefix_RECONSTRUCTION=Linear")
elif self.reconstruction == 3:
Expand Down
31 changes: 15 additions & 16 deletions src/fluid/boundary/axis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void Axis::ShowConfig() {
void Axis::SymmetrizeEx1Side(int jref, IdefixArray3D<real> Ex1) {
#if DIMENSIONS == 3

IdefixArray1D<real> Ex1Avg = this->Ex1Avg;
auto Ex1Avg = this->Ex1Avg.deviceView();

idefix_for("Ex1_ini",0,data->np_tot[IDIR],
KOKKOS_LAMBDA(int i) {
Expand All @@ -40,7 +40,7 @@ void Axis::SymmetrizeEx1Side(int jref, IdefixArray3D<real> Ex1) {
#ifdef WITH_MPI
Kokkos::fence();
// sum along all of the processes on the same r
MPI_Allreduce(MPI_IN_PLACE, Ex1Avg.data(), data->np_tot[IDIR], realMPI,
idfx::MPI_Allreduce(MPI_IN_PLACE, this->Ex1Avg, data->np_tot[IDIR], realMPI,
MPI_SUM, data->mygrid->AxisComm);
#endif
}
Expand Down Expand Up @@ -88,7 +88,8 @@ void Axis::RegularizeCurrentSide(int side) {
jc = data->end[JDIR]-1;
sign = -1;
}
IdefixArray1D<real> BAvg = this->Ex1Avg;
auto BAvg = this->Ex1Avg.deviceView();
auto BAvgComm = this->Ex1Avg;
IdefixArray1D<real> x1 = data->x[IDIR];
IdefixArray1D<real> dx3 = data->dx[KDIR];
IdefixArray1D<real> dx2 = data->dx[JDIR];
Expand All @@ -107,7 +108,7 @@ void Axis::RegularizeCurrentSide(int side) {
#ifdef WITH_MPI
Kokkos::fence();
// sum along all of the processes on the same r
MPI_Allreduce(MPI_IN_PLACE, BAvg.data(), data->np_tot[IDIR], realMPI,
MPI_Allreduce(MPI_IN_PLACE, BAvgComm, data->np_tot[IDIR], realMPI,
MPI_SUM, data->mygrid->AxisComm);
#endif
}
Expand Down Expand Up @@ -169,7 +170,7 @@ void Axis::FixBx2sAxis(int side) {
// Compute the values of Bx and By that are consistent with BX2 along the axis
#if DIMENSIONS == 3
IdefixArray4D<real> Vs = this->Vs;
IdefixArray2D<real> BAvg = this->BAvg;
auto BAvg = this->BAvg.deviceView();
IdefixArray1D<real> phi = data->x[KDIR];

int jin = 0;
Expand Down Expand Up @@ -208,7 +209,7 @@ void Axis::FixBx2sAxis(int side) {
Kokkos::fence();
#ifdef WITH_MPI
// sum along all of the processes on the same r
MPI_Allreduce(MPI_IN_PLACE, BAvg.data(), 2*data->np_tot[IDIR], realMPI,
idfx::MPI_Allreduce(MPI_IN_PLACE, this->BAvg, 2*data->np_tot[IDIR], realMPI,
MPI_SUM, data->mygrid->AxisComm);
#endif
}
Expand Down Expand Up @@ -392,7 +393,6 @@ void Axis::ExchangeMPI(int side) {
idfx::pushRegion("Axis::ExchangeMPI");
#ifdef WITH_MPI
// Load the buffers with data
[[maybe_unused]] int ibeg,iend,jbeg,jend,kbeg,kend;
int offset;
int ny;
Buffer bufferSend = this->bufferSend;
Expand All @@ -409,7 +409,7 @@ void Axis::ExchangeMPI(int side) {
MPI_Status recvStatus;

double tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Start(&recvRequest));
MPI_SAFE_CALL(idfx::MPI_Start(&recvRequest));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

// Coordinates of the ghost region which needs to be transfered
Expand Down Expand Up @@ -471,8 +471,8 @@ void Axis::ExchangeMPI(int side) {
Kokkos::fence();

tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Start(&sendRequest));
MPI_Wait(&recvRequest,&recvStatus);
MPI_SAFE_CALL(idfx::MPI_Start(&sendRequest));
idfx::MPI_Wait(&recvRequest,&recvStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

// Unpack
Expand Down Expand Up @@ -526,8 +526,7 @@ void Axis::ExchangeMPI(int side) {
} // MHD
}

MPI_Wait(&sendRequest, &sendStatus);

idfx::MPI_Wait(&sendRequest, &sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;


Expand Down Expand Up @@ -594,11 +593,11 @@ void Axis::InitMPI() {
MPI_SAFE_CALL(MPI_Cart_shift(data->mygrid->AxisComm,0,data->mygrid->nproc[KDIR]/2,
&procRecv,&procSend ));

MPI_SAFE_CALL(MPI_Send_init(bufferSend.data(), bufferSend.Size(), realMPI, procSend,
650, data->mygrid->AxisComm, &sendRequest));
MPI_SAFE_CALL(idfx::MPI_Send_init(bufferSend.commView(), bufferSend.Size(),
realMPI, procSend, 650, data->mygrid->AxisComm, &sendRequest));

MPI_SAFE_CALL(MPI_Recv_init(bufferRecv.data(), bufferRecv.Size(), realMPI, procRecv,
650, data->mygrid->AxisComm, &recvRequest));
MPI_SAFE_CALL(idfx::MPI_Recv_init(bufferRecv.commView(), bufferRecv.Size(),
realMPI, procRecv, 650, data->mygrid->AxisComm, &recvRequest));

#endif
idfx::popRegion();
Expand Down
12 changes: 6 additions & 6 deletions src/fluid/boundary/axis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class Axis {

enum {faceTop, faceBot};
#ifdef WITH_MPI
MPI_Request sendRequest;
MPI_Request recvRequest;
idfx::MPI_Request_1D<real> sendRequest;
idfx::MPI_Request_1D<real> recvRequest;

Buffer bufferSend;
Buffer bufferRecv;
Expand All @@ -71,8 +71,8 @@ class Axis {
#endif
void InitMPI();

IdefixArray1D<real> Ex1Avg;
IdefixArray2D<real> BAvg;
idfx::IdefixCommArray1D<real> Ex1Avg;
idfx::IdefixCommArray2D<real> BAvg;
bool haveCurrent;
IdefixArray2D<real> JAvg;
IdefixArray1D<int> symmetryVc;
Expand Down Expand Up @@ -155,8 +155,8 @@ Axis::Axis(Boundary<Phys> *boundary) {
}
Kokkos::deep_copy(symmetryVs, symmetryVsHost);

this->Ex1Avg = IdefixArray1D<real>("Axis:Ex1Avg",data->np_tot[IDIR]);
this->BAvg = IdefixArray2D<real>("Axis:BxAvg",data->np_tot[IDIR],2);
this->Ex1Avg = idfx::IdefixCommArray1D<real>("Axis:Ex1Avg",data->np_tot[IDIR]);
this->BAvg = idfx::IdefixCommArray2D<real>("Axis:BxAvg",data->np_tot[IDIR],2);
if(haveCurrent) {
this->JAvg = IdefixArray2D<real>("Axis:JAvg",data->np_tot[IDIR],3);
}
Expand Down
25 changes: 12 additions & 13 deletions src/fluid/constrainedTransport/EMFexchange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void ConstrainedTransport<Phys>::ExchangeX1(IdefixArray3D<real> ey, IdefixArray3
MPI_Status recvStatus[2];

double tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX1));
MPI_SAFE_CALL(idfx::MPI_Startall(2, recvRequestX1));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

BoundaryType lbound = data->lbound[IDIR];
Expand Down Expand Up @@ -82,11 +82,10 @@ void ConstrainedTransport<Phys>::ExchangeX1(IdefixArray3D<real> ey, IdefixArray3
Kokkos::fence();

tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX1));
MPI_SAFE_CALL(idfx::MPI_Startall(2, sendRequestX1));
// Wait for buffers to be received

MPI_Waitall(2,recvRequestX1,recvStatus);
MPI_Waitall(2, sendRequestX1, sendStatus);
idfx::MPI_Waitall(2,recvRequestX1,recvStatus);
idfx::MPI_Waitall(2, sendRequestX1, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

// Unpack
Expand Down Expand Up @@ -130,7 +129,7 @@ void ConstrainedTransport<Phys>::ExchangeX2(IdefixArray3D<real> ex, IdefixArray3
double tStart = MPI_Wtime();
MPI_Status sendStatus[2];
MPI_Status recvStatus[2];
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX2));
MPI_SAFE_CALL(idfx::MPI_Startall(2, recvRequestX2));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

BoundaryType lbound = data->lbound[JDIR];
Expand Down Expand Up @@ -169,10 +168,10 @@ void ConstrainedTransport<Phys>::ExchangeX2(IdefixArray3D<real> ex, IdefixArray3
Kokkos::fence();

tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX2));
MPI_SAFE_CALL(idfx::MPI_Startall(2, sendRequestX2));
// Wait for buffers to be received
MPI_Waitall(2, recvRequestX2, recvStatus);
MPI_Waitall(2, sendRequestX2, sendStatus);
idfx::MPI_Waitall(2, recvRequestX2, recvStatus);
idfx::MPI_Waitall(2, sendRequestX2, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

// Unpack
Expand Down Expand Up @@ -216,7 +215,7 @@ void ConstrainedTransport<Phys>::ExchangeX3(IdefixArray3D<real> ex, IdefixArray3
double tStart = MPI_Wtime();
MPI_Status sendStatus[2];
MPI_Status recvStatus[2];
MPI_SAFE_CALL(MPI_Startall(2, recvRequestX3));
MPI_SAFE_CALL(idfx::MPI_Startall(2, recvRequestX3));
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

BoundaryType lbound = data->lbound[KDIR];
Expand Down Expand Up @@ -256,10 +255,10 @@ void ConstrainedTransport<Phys>::ExchangeX3(IdefixArray3D<real> ex, IdefixArray3
Kokkos::fence();

tStart = MPI_Wtime();
MPI_SAFE_CALL(MPI_Startall(2, sendRequestX3));
MPI_SAFE_CALL(idfx::MPI_Startall(2, sendRequestX3));
// Wait for buffers to be received
MPI_Waitall(2, recvRequestX3, recvStatus);
MPI_Waitall(2, sendRequestX3, sendStatus);
idfx::MPI_Waitall(2, recvRequestX3, recvStatus);
idfx::MPI_Waitall(2, sendRequestX3, sendStatus);
idfx::mpiCallsTimer += MPI_Wtime() - tStart;

// Unpack
Expand Down
Loading