ParaMonte MATLAB 3.0.0
Parallel Monte Carlo and Machine Learning Library
See the latest version documentation.
detect.m
Go to the documentation of this file.
1%> \brief
2%> Return the MPI image count and current image ID (e.g., MPI rank + 1)
3%> and the MPI library name as it appears in the ParaMonte library path
4%> and the corresponding MPI-parallel ParaMonte library path .<br>
5%>
6%> \details
7%> This function attempts to detect the invocation of the
8%> current MATLAB session via checking the runtime behavior
9%> of the ``mpiexec`` binary MPI launcher instance.<br>
10%>
11%> Output values interpretation
12%> ----------------------------
13%>
14%> <ol>
15%> <li> If the output ``mpiname`` is set to an empty string ``""``,
16%> meaning that ``strcmp(mpiname, "")`` yields ``true``,
17%> then the algorithm has failed, implying that the current
18%> application is likely to have been launched by via an ``mpiexec``
19%> binary whose MPI library is supported by the ParaMonte library.<br>
20%> <li> If the output ``mpiname`` is set to an non-empty string,
21%> which must be the name of an MPI library vendor used within ParaMonte,<br>
22%> then an instance of the corresponding MPI library likely exists on the current system
23%> and its ``mpiexec`` binary has been used to launch the current application in parallel.<br>
24%> If so,<br>
25%> <ol>
26%> <li> A value of ``0`` for either of the output values ``nproc`` and ``rankp1``
27%> implies the algorithm failed to infer the corresponding parameters.<br>
28%> <li> A non-zero positive value for either or both of the output values ``nproc``
29%> and ``rankp1`` implies that the ``mpiexec`` MPI launcher binary of the
30%> corresponding MPI library **might have been used** to launch MATLAB
31%> and its might have been used to launch MATLAB.<br>
32%> <ol>
33%> <li> A non-zero positive value other than ``1`` for the output ``nproc``
34%> guarantees that the ``mpiexec`` launcher has been used to launch MATLAB
35%> with the specified ``nproc`` number of MPI images (processes).<br>
36%> </ol>
37%> </ol>
38%> </ol>
39%>
40%> \param[in] vendor : The input scalar MATLAB string, containing the MPI
41%> library vendor supported by the ParaMonte library.<br>
42%> Possible values are:<br>
43%> <ol>
44%> <li> ``OpenMPI``, representing the OpenMPI library.
45%> <li> ``MPICH``, representing the MPICH MPI library.
46%> <li> ``Intel``, representing the Intel MPI library.
47%> <li> ``any``, representing any available MPI library.<br>
48%> </ol>
49%> or any other informal name returned by the ParaMonte
50%> MATLAB function [pm.lib.mpi.name()](@ref name).<br>
51%> Note that **all values are case-insensitive**.<br>
52%> (**optional, default = ``"any"``.)
53%>
54%> \return
55%> ``mpiname`` : The output scalar MATLAB string containing the MPI
56%> library name as it appears in the ParaMonte library path.<br>
57%> An output value of ``""`` implies the algorithm failed to detect
58%> a ParaMonte-compatible MPI library invoked or installed on the system.<br>
59%> ``nproc`` : The output scalar MATLAB non-negative whole number containing
60%> the number of MPI images in the current invocation of the
61%> ``mpiexec`` binary MPI launcher.<br>
62%> An output value of ``0`` implies the algorithm failed to detect
63%> a ParaMonte-compatible MPI library or failed to infer the image count.<br>
64%> ``rankp1`` : The output scalar MATLAB non-negative whole number containing
65%> the image ID (e.g., MPI rank + 1) of the current MPI image in
66%> the current invocation of the ``mpiexec`` binary MPI launcher.<br>
67%> An output value of ``0`` implies the algorithm failed to detect
68%> a ParaMonte-compatible MPI library or failed to infer the image count.<br>
69%> Note that the image ID always starts at ``1``, unlike the MPI rank.<br>
70%> The argument ``rankp1`` stands for ``rank + 1``.<br>
71%>
72%> \interface{detect}
73%> \code{.m}
74%>
75%> [mpiname, nproc, rankp1] = pm.lib.mpi.runtime.detect();
76%> [mpiname, nproc, rankp1] = pm.lib.mpi.runtime.detect(vendor);
77%>
78%> \endcode
79%>
80%> \warning
81%> This routine must be called before the MPI library is finalized by any other application.<br>
82%> Example applications that finalize the MPI library upon return includes the ParaMonte MPI-parallel samplers.<br>
83%> However, each application offers an option to prevent the default finalization of the MPI library.<br>
84%> For this reason, the results of this function are saved within the function for subsequent usage after the first call.<br>
85%>
86%> \note
87%> This function internally uses a ``persistent`` MATLAB ``struct``
88%> to store the results for the default input value for ``vendor``
89%> to expedite future inquiries using this function.<br>
90%> Specifying an input argument value will always
91%>
92%> \example{detect}
93%> \include{lineno} example/lib/mpi/detect/main.m
94%> \output{detect}
95%> \include{lineno} example/lib/mpi/detect/main.out.m
96%>
97%> \todo
98%> \phigh
99%> The internals of this function can be improved for better efficiency and less redundancy.<br>
100%>
101%> \final{detect}
102%>
103%> \author
104%> \AmirShahmoradi, 2:27 AM Monday, November 11, 2024, Dallas, TX<br>
105function [mpiname, nproc, rankp1] = detect(vendor)
106
107 if nargin < 1
108 vendor = [];
109 end
110
111 if pm.array.len(vendor) == 0
112 vendor = "any";
113 end
114
115 %%%%
116 %%%% Get the name list of available ParaMonte-compatible MPI library names.
117 %%%%
118
119 allnames = pm.lib.mpi.choices();
120 isall = strcmpi(vendor, "any") || strcmpi(vendor, "all");
121 if ~isall
122 thisname = pm.lib.mpi.name(vendor);
123 isall = strcmpi(thisname, "mpi");
124 end
125 if isall
126 mpinames = allnames;
127 else
128 mpinames = thisname;
129 end
130
131 %%%%
132 %%%% Get the name list of available ParaMonte-compatible MPI library names.
133 %%%%
134
135 nproc = 0;
136 rankp1 = 0;
137 mpiname = "";
138 for iname = 1 : numel(allnames)
139 thisname = allnames(iname);
140 if any(contains(mpinames, thisname))
141 if strcmp(thisname, "openmpi")
142 [nproc, rankp1] = pm.lib.mpi.runtime.ompi();
143 elseif strcmp(thisname, "mpich")
144 [nproc, rankp1] = pm.lib.mpi.runtime.mmpi();
145 elseif strcmp(thisname, "impi")
146 [nproc, rankp1] = pm.lib.mpi.runtime.impi();
147 end
148 if nproc ~= 0 && rankp1 ~= 0
149 mpiname = thisname;
150 return;
151 end
152 end
153
154 end
155
156 % persistent output;
157 % output = struct();
158 %
159 % if nargin < 1
160 % vendor = [];
161 % end
162 %
163 % if pm.array.len(vendor) == 0
164 % vendor = "any";
165 % end
166 %
167 % %%%%
168 % %%%% Get a list of MPI nproc/rank binaries in the current ParaMonte library instance.
169 % %%%%
170 %
171 % %mpinames = ["mpi", "impi", "mpich", "openmpi"];
172 % if ~strcmpi(vendor, "any") && ~strcmpi(vendor, "all")
173 % mpidirpattern = "**" + pm.lib.mpi.name(vendor);
174 % else
175 % mpidirpattern = "";
176 % end
177 %
178 % bindirs = pm.sys.path.glob(pm.lib.path.lib() + mpidirpattern + "**xgetImageStatMPI*");
179 %
180 % %%%%
181 % %%%% Loop over the binaries to test them for MPI compatibility.
182 % %%%% Beware that some MPI libraries may be compatible but not function correctly when mixed.
183 % %%%% Therefore, we will test for the MPI world size larger than ``1`` as an MPI detection.
184 % %%%%
185 %
186 % nprocmax = -1;
187 % for iname = 1 : numel(bindirs)
188 %
189 % %%%%
190 % %%%% Find the MPI name in the current ParaMonte library instance.
191 % %%%%
192 %
193 % [basedir, ~, ~] = fileparts(bindirs{iname});
194 % [basedir, ~, ~] = fileparts(basedir);
195 % [~, dirname, ~] = fileparts(string(basedir));
196 % dirname = string(dirname);
197 %
198 % isfresh = true;
199 % if ~isempty(fields(output))
200 % for field = string(fields(output))
201 % isfresh = ~strcmp(dirname, field);
202 % if ~isfresh
203 % break;
204 % end
205 % end
206 % end
207 %
208 % %%%%
209 % %%%% Test the MPI vendor compatibility only if it is a fresh search.
210 % %%%%
211 %
212 % if isfresh
213 %
214 % output.(dirname) = struct();
215 % output.(dirname).mpiname = "";
216 % output.(dirname).bindir = "";
217 % output.(dirname).rankp1 = 0;
218 % output.(dirname).nproc = 0;
219 %
220 % %%%%
221 % %%%% Execute the MPI image status binary.
222 % %%%%
223 %
224 % [status, cmdout] = system(bindirs{iname});
225 % cmdout = string(cmdout);
226 %
227 % if status == 0
228 %
229 % %if strcmp(output.mpiname, "")
230 % % warning ( newline ...
231 % % + "Unrecognized MPI library name detected among the ParaMonte library paths:" + newline ...
232 % % + newline ...
233 % % + pm.io.tab + string(output.mpiname) + newline ...
234 % % + newline ...
235 % % + "The corresponding ParaMonte library path is: " + newline ...
236 % % + newline ...
237 % % + pm.io.tab + bindirs(iname) + newline ...
238 % % + newline ...
239 % % + "The expected MPI library names are: " + newline ...
240 % % + newline ...
241 % % + pm.io.tab + strjoin(mpinames, ", ") + newline ...
242 % % + newline ...
243 % % );
244 % %else
245 % % return;
246 % %end
247 %
248 % %%%%
249 % %%%% Search for the keyword `imageCountRank`.
250 % %%%%
251 %
252 % if contains(cmdout, "imageCountRank")
253 %
254 % tokens = strsplit(cmdout, "imageCountRank");
255 % output.(dirname).nproc = str2double(tokens(2));
256 % output.(dirname).rankp1 = str2double(tokens(3));
257 % output.(dirname).bindir = bindirs(iname);
258 % output.(dirname).mpiname = dirname;
259 % %break;
260 %
261 % end
262 %
263 % end
264 %
265 % end
266 %
267 % %%%%
268 % %%%% Select the MPI library with the highest ``nproc``.
269 % %%%%
270 %
271 % if nprocmax < output.(dirname).nproc
272 % nprocmax = output.(dirname).nproc;
273 % selection = output.(dirname).mpiname;
274 % end
275 %
276 % end
277 %
278 % mpiname = output.(selection).mpiname;
279 % bindir = output.(selection).bindir;
280 % rankp1 = output.(selection).rankp1;
281 % nproc = output.(selection).nproc;
282 %
283 % if nargin > 0
284 % output = [];
285 % end
286
287end
function name(in vendor)
Return the MPI library name as used in naming the ParaMonte MATLAB shared library directories.
function vendor(in name)
Return the MPI library vendor name from the input MPI name based on the internal ParaMonte shared lib...
function list()
Return a list of MATLAB strings containing the names of OS platforms supported by the ParaMonte MATLA...
function detect(in vendor)
Return the MPI image count and current image ID (e.g., MPI rank + 1) and the MPI library name as it a...
function lib()
Return a scalar MATLAB string containing the path to the lib directory of the ParaMonte library packa...
function nproc(in vendor)
Return the runtime number of MPI processes with which the mpiexec launcher may have been invoked.
function parallel()
Return a scalar MATLAB logical that is true if and only if the current installation of MATLAB contain...
function rankp1(in vendor)
Return the ID (MPI rank + 1) of the current MPI image (process), starting from the number one.
function which(in vendor)
Return the a MATLAB string containing the path to the first mpiexec executable binary found in system...