Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ArcaneMpi.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ArcaneMpi.cc (C) 2000-2026 */
9/* */
10/* Global declarations for the MPI part of Arcane. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/parallel/mpi/ArcaneMpi.h"
15
16#include "arcane/utils/String.h"
17#include "arcane/impl/ArcaneMain.h"
18#include "arcane/core/ApplicationBuildInfo.h"
19
20#include <iostream>
21
22// This file is used by OpenMpi to define extensions
23// The page https://www.open-mpi.org/faq/?category=runcuda
24// indicates how to detect if we are CUDA-AWARE.
25
26#if __has_include(<mpi-ext.h>)
27#include <mpi-ext.h>
28#endif
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39extern "C++" ARCANE_MPI_EXPORT bool
41{
42 bool is_aware = false;
43 // OpenMPI defines MPIX_CUDA_AWARE_SUPPORT and mpich defines MPIX_GPU_SUPPORT_CUDA
44 // to indicate that MPIX_Query_cuda_support() is available.
45#if defined(ARCANE_OS_LINUX)
46#if defined(MPIX_CUDA_AWARE_SUPPORT) || defined(MPIX_GPU_SUPPORT_CUDA)
47 is_aware = (MPIX_Query_cuda_support() == 1);
48#endif
49#endif
50 return is_aware;
51}
52
53extern "C++" ARCANE_MPI_EXPORT bool
54arcaneIsHipAwareMPI()
55{
56 bool is_aware = false;
57 // OpenMPI defines MPIX_HIP_AWARE_SUPPORT and mpich defines MPIX_GPU_SUPPORT_HIP
58 // to indicate that MPIX_Query_hip_support() is available.
59
60 // MPICH
61#if defined(ARCANE_OS_LINUX)
62#if defined(MPIX_GPU_SUPPORT_HIP)
63 // CRAY MPICH
64#if defined(CRAY_MPICH_VERSION)
65 int is_supported = 0;
66 MPIX_GPU_query_support(MPIX_GPU_SUPPORT_HIP, &is_supported);
67 is_aware = (is_supported != 0);
68#else
69 is_aware = (MPIX_Query_hip_support() == 1);
70#endif
71#endif
72
73 // OpenMPI:
74#if defined(MPIX_ROCM_AWARE_SUPPORT)
75 is_aware = (MPIX_Query_rocm_support() == 1);
76#endif
77#endif
78 return is_aware;
79}
80
81/*---------------------------------------------------------------------------*/
82/*---------------------------------------------------------------------------*/
83
84extern "C++" ARCANE_MPI_EXPORT bool
86{
87 return arcaneIsCudaAwareMPI() || arcaneIsHipAwareMPI();
88}
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
97class MpiAutoInit
98{
99 public:
100
101 MpiAutoInit() = default;
102
103 public:
104
105 void initialize(int* argc, char*** argv, int wanted_thread_level)
106 {
107 int is_init = 0;
108 MPI_Initialized(&is_init);
109
110 if (is_init != 0)
111 return;
112
113 int thread_provided = 0;
114 MPI_Init_thread(argc, argv, wanted_thread_level, &thread_provided);
115 m_need_finalize = true;
116 }
117
118 void finalize()
119 {
120 if (m_need_finalize) {
121 MPI_Finalize();
122 m_need_finalize = false;
123 }
124 }
125
126 private:
127
128 bool m_need_finalize = false;
129};
130
131/*---------------------------------------------------------------------------*/
132/*---------------------------------------------------------------------------*/
133
136{
137 public:
138
139 void visit(ApplicationBuildInfo& app_build_info) override;
140};
141
142/*---------------------------------------------------------------------------*/
143/*---------------------------------------------------------------------------*/
157visit(ApplicationBuildInfo& app_build_info)
158{
159 String message_passing_service = app_build_info.messagePassingService();
160 bool need_init = message_passing_service != "SequentialParallelSuperMng";
161 bool has_shared_memory_message_passing = app_build_info.nbSharedMemorySubDomain() > 0;
162
163 // If MPI has not been initialized, we do it here.
164 // We choose the thread level based on the number of
165 // shared memory subdomains specified. If there is no memory
166 // shared, it takes MPI_THREAD_SERIALIZED.
167 int thread_wanted = MPI_THREAD_SERIALIZED;
168 if (has_shared_memory_message_passing)
169 thread_wanted = MPI_THREAD_MULTIPLE;
170
171 int comm_size = 0;
172
173 // We do not initialize if the requested service is 'Sequential'.
174 if (need_init) {
175 // TODO: use the correct arguments.
176 int* argc = nullptr;
177 char*** argv = nullptr;
178 arcaneInitializeMPI(argc, argv, thread_wanted);
179
180 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
181 }
182
183 // Sets the default exchange service.
184 // Note that this will not be used if the user
185 // has specified a service themselves
186 message_passing_service = "Sequential";
187 if (comm_size > 1) {
188 if (has_shared_memory_message_passing)
189 message_passing_service = "Hybrid";
190 else
191 message_passing_service = "Mpi";
192 }
193 else {
194 if (has_shared_memory_message_passing)
195 message_passing_service = "MpiSharedMemory";
196 else
197 message_passing_service = "MpiSequential";
198 }
199 message_passing_service = message_passing_service + "ParallelSuperMng";
200 // Changes the default service.
201 app_build_info.internalSetDefaultMessagePassingService(message_passing_service);
202}
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
207namespace
208{
209 MpiAutoInit global_mpi_auto_init;
210 AutoDetecterMPI global_autodetecter_mpi;
211 bool global_already_added = false;
212} // namespace
213
214/*---------------------------------------------------------------------------*/
215/*---------------------------------------------------------------------------*/
216
217extern "C" ARCANE_MPI_EXPORT void
219{
220 if (!global_already_added)
221 ArcaneMain::addApplicationBuildInfoVisitor(&global_autodetecter_mpi);
222 global_already_added = true;
223}
224
225extern "C++" ARCANE_MPI_EXPORT void
226arcaneInitializeMPI(int* argc, char*** argv, int wanted_thread_level)
227{
228 global_mpi_auto_init.initialize(argc, argv, wanted_thread_level);
229}
230
231extern "C++" ARCANE_MPI_EXPORT void
233{
234 global_mpi_auto_init.finalize();
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240} // End namespace Arcane.
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
Information for constructing an instance of IApplication.
void internalSetDefaultMessagePassingService(const String &name)
Default message passing manager name. Must only be modified by Arcane.
static void addApplicationBuildInfoVisitor(IApplicationBuildInfoVisitor *visitor)
Adds a visitor to fill ApplicationBuildInfo.
void visit(ApplicationBuildInfo &app_build_info) override
Fills default values for message passing services.
Definition ArcaneMpi.cc:157
Singleton class to automatically call MPI_Init and MPI_Finalize if necessary. MPI_Finalize is only ca...
Definition ArcaneMpi.cc:98
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ARCANE_MPI_EXPORT void arcaneInitializeMPI(int *argc, char ***argv, int wanted_thread_level)
Definition ArcaneMpi.cc:226
ARCANE_MPI_EXPORT bool arcaneIsAcceleratorAwareMPI()
Indicates if the current MPI runtime supports accelerators.
Definition ArcaneMpi.cc:85
ARCANE_MPI_EXPORT bool arcaneIsCudaAwareMPI()
Indicates if the current MPI runtime supports CUDA.
Definition ArcaneMpi.cc:40
ARCANE_MPI_EXPORT void arcaneAutoDetectMessagePassingServiceMPI()
Mechanism to automatically initialize MPI and Arcane's message exchange services based on Application...
Definition ArcaneMpi.cc:218
ARCANE_MPI_EXPORT void arcaneFinalizeMPI()
Definition ArcaneMpi.cc:232