Skip to content

Commit deff290

Browse files
committed
MPIABI => MPIPreferences
1 parent 50db836 commit deff290

File tree

4 files changed

+163
-80
lines changed

4 files changed

+163
-80
lines changed

lib/MPIABI/src/MPIABI.jl

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
name = "MPIABI"
1+
name = "MPIPreferences"
22
uuid = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267"
33
authors = []
44
version = "0.1.0"
55

66
[deps]
7+
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
78
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
File renamed without changes.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
module MPIPreferences
2+
3+
using Preferences, Libdl
4+
5+
const binary = @load_preference("binary", Sys.iswindows() ? "MicrosoftMPI_jll" : "MPICH_jll")
6+
7+
const abi = if binary == "system"
8+
@load_preference("abi")
9+
elseif binary == "MicrosoftMPI_jll"
10+
"MicrosoftMPI"
11+
elseif binary == "MPICH_jll"
12+
"MPICH"
13+
elseif binary == "OpenMPI_jll"
14+
"OpenMPI"
15+
elseif binary == "MPItrampoline_jll"
16+
"MPItrampoline"
17+
else
18+
error("Unknown binary: $binary")
19+
end
20+
21+
module System
22+
using Preferences
23+
const libmpi = @load_preference("libmpi")
24+
const mpiexec_path = @load_preference("mpiexec")
25+
mpiexec() = `$mpiexec_path`
26+
mpiexec(f) = f(`$mpiexec_path`)
27+
end
28+
29+
function use_jll_binary(binary = Sys.iswindows() ? "MicrosoftMPI_jll" : "MPICH_jll")
30+
binary in ["MicrosoftMPI_jll", "MPICH_jll", "OpenMPI_jll", "MPItrampoline_jll"] ||
31+
error("Unknown jll: $binary")
32+
@set_preferences!(
33+
"binary" => binary,
34+
"libmpi" => nothing,
35+
"abi" => nothing,
36+
"mpiexec" => nothing
37+
)
38+
end
39+
40+
function use_system_binary(;
41+
library=["libmpi", "libmpi_ibm", "msmpi", "libmpich", "libmpitrampoline"],
42+
mpiexec="mpiexec",
43+
abi=nothing,
44+
)
45+
46+
libmpi = find_library(library)
47+
if libmpi == ""
48+
error("MPI library could not be found")
49+
end
50+
if isnothing(abi)
51+
versionstring = Get_library_version(libmpi)
52+
impl, version = identify_implementation(versionstring)
53+
abi = identify_abi(impl, version)
54+
end
55+
if mpiexec isa Cmd
56+
mpiexec = collect(mpiexec)
57+
end
58+
@set_preferences!(
59+
"binary" => "system",
60+
"libmpi" => libmpi,
61+
"abi" => abi,
62+
"mpiexec" => mpiexec,
63+
)
64+
end
65+
66+
67+
function Get_library_version(libmpi)
68+
# There is no way to query at runtime what the length of the buffer should be.
69+
# https://github.com/mpi-forum/mpi-issues/issues/159
70+
# 8192 is the maximum value of MPI_MAX_LIBRARY_VERSION_STRING across known
71+
# implementations.
72+
buf = Array{UInt8}(undef, 8192)
73+
buflen = Ref{Cint}()
74+
dlopen(libmpi) do hdl
75+
ptr = dlsym(hdl, :MPI_Get_library_version)
76+
ccall(ptr, Cint, (Ptr{UInt8}, Ref{Cint}), buf, buflen)
77+
end
78+
79+
@assert buflen[] < 8192
80+
resize!(buf, buflen[])
81+
return String(buf)
82+
end
83+
84+
85+
"""
86+
identify_abi(version_string)
87+
88+
Identify the MPI implementation from the library version string
89+
"""
90+
function identify_abi(version_string::String)
91+
impl = "unknown"
92+
version = v"0"
93+
94+
if startswith(version_string, "MPICH")
95+
impl = "MPICH"
96+
# "MPICH Version:\t%s\n" / "MPICH2 Version:\t%s\n"
97+
if (m = match(r"^MPICH2? Version:\t(\d+.\d+(?:.\d+)?\w*)\n", version_string)) !== nothing
98+
version = VersionNumber(m.captures[1])
99+
end
100+
101+
elseif startswith(version_string, "Open MPI")
102+
# Open MPI / Spectrum MPI
103+
impl = occursin("IBM Spectrum MPI", version_string) ? "IBMSpectrumMPI" : "OpenMPI"
104+
105+
if (m = match(r"^Open MPI v(\d+.\d+.\d+\w*)", version_string)) !== nothing
106+
version = VersionNumber(m.captures[1])
107+
end
108+
109+
elseif startswith(version_string, "Microsoft MPI")
110+
impl = "MicrosoftMPI"
111+
# "Microsoft MPI %u.%u.%u.%u%S"
112+
# ignore last 2 (build numbers)
113+
if (m = match(r"^Microsoft MPI (\d+.\d+)", version_string)) !== nothing
114+
version = VersionNumber(m.captures[1])
115+
end
116+
117+
elseif startswith(version_string, "Intel")
118+
impl = "IntelMPI"
119+
120+
# "Intel(R) MPI Library 2019 Update 4 for Linux* OS"
121+
if (m = match(r"^Intel\(R\) MPI Library (\d+)(?: Update (\d+))?", version_string)) !== nothing
122+
if m.captures[2] === nothing
123+
version = VersionNumber(m.captures[1])
124+
else
125+
version = VersionNumber(m.captures[1]*"."*m.captures[2])
126+
end
127+
end
128+
129+
elseif startswith(version_string, "MVAPICH2")
130+
impl = "MVAPICH"
131+
# "MVAPICH2 Version :\t%s\n")
132+
if (m = match(r"^MVAPICH2? Version\s*:\t(\S*)\n", version_string)) !== nothing
133+
version = VersionNumber(m.captures[1])
134+
end
135+
136+
elseif occursin("CRAY MPICH", version_string)
137+
impl = "CrayMPICH"
138+
# "MPI VERSION : CRAY MPICH version 7.7.10 (ANL base 3.2)\n"
139+
if (m = match(r"CRAY MPICH version (\d+.\d+.\d+)", version_string)) !== nothing
140+
version = VersionNumber(m.captures[1])
141+
end
142+
end
143+
144+
# determine the abi from the implementation + version
145+
if (impl == "MPICH" && version >= v"3.1" ||
146+
impl == "IntelMPI" && version > v"2014" ||
147+
impl == "MVAPICH" && version >= v"2" ||
148+
impl == "CrayMPICH" && version >= v"7")
149+
# https://www.mpich.org/abi/
150+
abi = "MPICH"
151+
elseif impl == "OpenMPI" || impl == "IBMSpectrumMPI"
152+
abi = "OpenMPI"
153+
elseif impl == "MicrosoftMPI"
154+
abi = "MicrosoftMPI"
155+
else
156+
abi = "unknown"
157+
end
158+
return abi
159+
end
160+
161+
end # module

0 commit comments

Comments
 (0)