Skip to content

Commit dd393a8

Browse files
committed
Support for Open MPI
1 parent 9fc9988 commit dd393a8

10 files changed

+314
-18
lines changed

.codespellrc

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# https://github.com/codespell-project/codespell #-*- mode: conf -*-
2+
3+
[codespell]
4+
ignore-words-list = pevent

.github/workflows/cd-wheel.yml

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ on: # yamllint disable-line rule:truthy
77
workflow_call:
88
inputs:
99
mpiname:
10-
description: 'MPI'
10+
description: 'MPI Name'
1111
default: 'mpich'
1212
required: false
1313
type: string
1414
version:
15-
description: 'Version'
15+
description: 'MPI Version'
1616
default: ''
1717
required: false
1818
type: string
@@ -39,6 +39,7 @@ on: # yamllint disable-line rule:truthy
3939
type: choice
4040
options:
4141
- mpich
42+
- openmpi
4243
version:
4344
description: 'Version'
4445
default: ''
@@ -122,6 +123,11 @@ jobs:
122123
- id: checkout
123124
uses: actions/checkout@v4
124125

126+
- id: setup-autotools
127+
if: ${{ runner.os == 'macOS' && runner.arch == 'ARM64' }}
128+
run: |
129+
brew install autoconf automake libtool
130+
125131
- id: setup-gfortran
126132
if: ${{ runner.os == 'macOS' }}
127133
run: |

.github/workflows/cd.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ on: # yamllint disable-line rule:truthy
77
workflow_dispatch:
88
inputs:
99
mpiname:
10-
description: 'MPI'
10+
description: 'MPI Name'
1111
default: 'mpich'
1212
type: choice
1313
options:
1414
- mpich
15+
- openmpi
1516
version:
16-
description: 'Version'
17+
description: 'MPI Version'
1718
default: ''
1819
required: false
1920
type: string

README.md

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
1-
# mpich-publish
1+
# mpi-publish
22

3-
This repository builds and publishes [MPICH](https://mpich.org)
4-
Python wheels able to run in a variety of
3+
This repository builds and publishes [MPICH](https://www.mpich.org) and
4+
[Open MPI](https://www.open-mpi.org/) Python wheels able to run in
5+
a variety of
56

67
- operating systems: *Linux*, *macOS*;
78
- processor architectures: *AMD64*, *ARM64*, *PPC64*;
89
- Python implementations: *CPython*, *PyPy*.
910

10-
MPICH wheels are uploaded to the [Anaconda.org](https://anaconda.org/mpi4py)
11+
MPI wheels are uploaded to the [Anaconda.org](https://anaconda.org/mpi4py)
1112
package server. These wheels can be installed with `pip` specifying the
1213
alternative index URL:
1314

1415
```sh
1516
python -m pip install mpich -i https://pypi.anaconda.org/mpi4py/simple
1617
```
1718

19+
```sh
20+
python -m pip install openmpi -i https://pypi.anaconda.org/mpi4py/simple
21+
```
22+
1823
> [!CAUTION]
19-
> MPICH wheels are distributed with a focus on ease of use, compatibility,
20-
> and interoperability. The Linux MPICH wheels are built in somewhat
21-
> constrained environments with relatively dated Linux distributions
24+
> MPI wheels are distributed with a focus on ease of use, compatibility, and
25+
> interoperability. The Linux wheels are built in somewhat constrained
26+
> environments with relatively dated Linux distributions
2227
> ([manylinux](https://github.com/pypa/manylinux) container images).
2328
> Therefore, they may lack support for high-performance features like
2429
> cross-memory attach (XPMEM/CMA). In production scenarios, it is recommended
25-
> to use external (either custom-built or system-provided) MPICH
26-
> installations.
30+
> to use external (either custom-built or system-provided) MPI installations.
2731
2832
> [!TIP]
2933
> [Intel MPI](https://software.intel.com/intel-mpi-library) distributes [Linux

bootstrap.sh

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,24 @@ set -euo pipefail
33

44
mpiname=${MPINAME:-mpich}
55

6+
PROJECT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
7+
PACKAGE=$PROJECT/package
8+
SOURCE=$PACKAGE/source
9+
610
if test "$mpiname" = "mpich"; then
711
version=${VERSION:-4.2.0}
812
urlbase="https://www.mpich.org/static/downloads/$version"
913
tarball="$mpiname-$version.tar.gz"
1014
license=COPYRIGHT
1115
fi
1216

13-
SOURCE=package/source
17+
if test "$mpiname" = "openmpi"; then
18+
version=${VERSION:-5.0.2}
19+
urlbase=https://download.open-mpi.org/release/open-mpi/v${version%.*}
20+
tarball="$mpiname-$version.tar.gz"
21+
license=LICENSE
22+
fi
23+
1424
if test ! -d "$SOURCE"; then
1525
if test ! -f "$tarball"; then
1626
echo downloading "$urlbase"/"$tarball"...
@@ -21,6 +31,14 @@ if test ! -d "$SOURCE"; then
2131
echo extracting "$tarball" to "$SOURCE"...
2232
tar xf "$tarball"
2333
mv "$mpiname-$version" "$SOURCE"
34+
if test "$mpiname-$(uname)" = "openmpi-Darwin"; then
35+
cd "$SOURCE"/3rd-party
36+
tar xf libevent-*.tar.gz
37+
cd libevent-*
38+
echo running autogen.sh on "$(basename "$(pwd)")"
39+
./autogen.sh
40+
cd "$PROJECT"
41+
fi
2442
else
2543
echo reusing directory "$SOURCE"...
2644
fi

check-wheel.sh

+23
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,29 @@ if test "$mpiname" = "mpich"; then
7474
fi
7575
fi
7676

77+
if test "$mpiname" = "openmpi"; then
78+
headers=(
79+
"$data"/include/mpi.h
80+
)
81+
scripts=(
82+
"$data"/bin/mpicc
83+
"$data"/bin/mpic++
84+
"$data"/bin/mpicxx
85+
"$data"/bin/mpiexec
86+
"$data"/bin/mpirun
87+
)
88+
programs=(
89+
"$data"/bin/ompi_info
90+
"$data"/bin/opal_wrapper
91+
)
92+
libraries=(
93+
"$data"/lib/libmpi.*
94+
"$data"/lib/libopen-*.*
95+
)
96+
runlibs+='|lib(z|util|event.*|hwloc)'$soregex
97+
runlibs+='|lib(open-(pal|rte)|pmix)'$soregex
98+
fi
99+
77100
check-dso() {
78101
local dso=$1 out1="" out2=""
79102
echo checking "$dso"...

cibw-build-mpi.sh

+172-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ set -euo pipefail
44
mpiname="${MPINAME:-mpich}"
55
variant="${VARIANT:-}"
66

7-
SOURCE=${SOURCE:-$PWD/package/source}
8-
WORKDIR=${WORKDIR:-$PWD/package/workdir}
9-
DESTDIR=${DESTDIR:-$PWD/package/install}
7+
PROJECT=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
8+
PACKAGE=$PROJECT/package
9+
10+
SOURCE=${SOURCE:-$PACKAGE/source}
11+
WORKDIR=${WORKDIR:-$PACKAGE/workdir}
12+
DESTDIR=${DESTDIR:-$PACKAGE/install}
1013
PREFIX=${PREFIX:-"/opt/$mpiname"}
1114

1215
if test "$mpiname" = "mpich"; then
@@ -40,6 +43,30 @@ if test "$mpiname" = "mpich"; then
4043
sed -i.orig "$disable_doc" "$SOURCE"/Makefile.in
4144
fi
4245

46+
if test "$mpiname" = "openmpi"; then
47+
options=(
48+
--enable-debug # FIXME
49+
CC=cc
50+
CXX=c++
51+
--prefix="$PREFIX"
52+
--disable-dlopen
53+
--disable-oshmem
54+
--without-ofi
55+
--without-ucx
56+
--without-psm2
57+
--without-cuda
58+
--without-rocm
59+
--with-pmix=internal
60+
--with-prrte=internal
61+
--with-libevent=internal
62+
--with-hwloc=internal
63+
--disable-static
64+
--disable-sphinx
65+
)
66+
if test "$(uname)" = Darwin; then
67+
options=("${options[@]/--disable-static}") # libevent
68+
fi
69+
fi
4370

4471
if test "$(uname)" = Darwin; then
4572
export MACOSX_DEPLOYMENT_TARGET="11.0"
@@ -170,5 +197,147 @@ fi
170197

171198
} # fixup-mpich()
172199

200+
fixup-openmpi() {
201+
202+
cd "${DESTDIR}${PREFIX}"
203+
rm -fr include/ev*
204+
rm -fr include/hwloc*
205+
rm -fr include/pmix*
206+
rm -fr include/prte*
207+
rm -f include/mpif*.h
208+
rm -f include/*/*/*mpifh.h
209+
rm -f bin/ev*
210+
rm -f bin/hwloc*
211+
rm -f bin/lstopo*
212+
213+
#rm -f bin/pmix_info
214+
rm -f bin/palloc
215+
rm -f bin/pattrs
216+
rm -f bin/pctrl
217+
rm -f bin/pevent
218+
rm -f bin/plookup
219+
rm -f bin/pps
220+
rm -f bin/pquery
221+
222+
#rm -f bin/prte_info
223+
#rm -f bin/prte
224+
#rm -f bin/prted
225+
#rm -f bin/prterun
226+
rm -f bin/prun
227+
rm -f bin/psched
228+
rm -f bin/pterm
229+
230+
rm -fr sbin
231+
rm -f bin/pmixcc
232+
rm -f bin/mpif77
233+
rm -f bin/mpif90
234+
rm -f bin/mpifort
235+
rm -f bin/oshrun
236+
rm -f lib/*.mod
237+
rm -f lib/lib*.a
238+
rm -f lib/lib*.la
239+
rm -f lib/libmpi_mpifh*.*
240+
rm -f lib/libmpi_usempi*.*
241+
rm -f lib/libompitrace.*
242+
rm -fr lib/openmpi
243+
rm -fr lib/pkgconfig
244+
rm -fr share/bash-completion
245+
rm -fr share/doc
246+
rm -fr share/man
247+
rm -fr share/hwloc
248+
rm -fr share/prte/rst
249+
rm -f share/openmpi/mpif77-wrapper-data.txt
250+
rm -f share/openmpi/mpif90-wrapper-data.txt
251+
rm -f share/openmpi/mpifort-wrapper-data.txt
252+
rm -f share/pmix/pmixcc-wrapper-data.txt
253+
rm -f share/*/*.supp
254+
rm -f share/*/*/example.conf
255+
256+
cd "${DESTDIR}${PREFIX}/bin"
257+
unset executables
258+
for exe in 'mpirun' 'ompi*' 'pmix*' 'prte*' 'opal*' 'orte*'; do
259+
while IFS= read -r filename
260+
do executables+=("$(basename "$filename")")
261+
done < <(find . -name "$exe" -type f)
262+
done
263+
264+
cd "${DESTDIR}${PREFIX}/lib"
265+
unset libraries
266+
for lib in 'lib*.so.*' 'lib*.*.dylib'; do
267+
while IFS= read -r filename
268+
do libraries+=("$(basename "$filename")")
269+
done < <(find . -name "$lib" -type f)
270+
done
271+
272+
if test "$(uname)" = Linux; then
273+
cd "${DESTDIR}${PREFIX}/bin"
274+
for exe in "${executables[@]}"; do
275+
patchelf --set-rpath "\$ORIGIN/../lib" "$exe"
276+
done
277+
cd "${DESTDIR}${PREFIX}/lib"
278+
for lib in lib*.so; do
279+
patchelf --set-rpath "\$ORIGIN" "$lib"
280+
soname=$(patchelf --print-soname "$lib")
281+
if test -L "$soname"; then
282+
mv "$(readlink "$soname")" "$soname"
283+
ln -sf "$soname" "$lib"
284+
fi
285+
done
286+
fi
287+
288+
if test "$(uname)" = Darwin; then
289+
cd "${DESTDIR}${PREFIX}/bin"
290+
for exe in "${executables[@]}"; do
291+
install_name_tool -add_rpath "@executable_path/../lib/" "$exe"
292+
unset dependencies
293+
while IFS= read -r dep
294+
do dependencies+=("$dep")
295+
done < <(otool -L "$exe" | sed 1,1d)
296+
for dep in "${dependencies[@]}"; do
297+
if test "$(dirname "$dep")" = "$(dirname "$PREFIX/lib/.")"; then
298+
installname="@rpath/$(basename "$dep")"
299+
install_name_tool -change "$dep" "$installname" "$exe"
300+
fi
301+
done
302+
done
303+
cd "${DESTDIR}${PREFIX}/lib"
304+
for lib in lib*.*.dylib; do
305+
install_name_tool -id "@rpath/$lib" "$lib"
306+
install_name_tool -add_rpath "@loader_path/" "$lib"
307+
while IFS= read -r dep
308+
do dependencies+=("$dep")
309+
done < <(otool -L "$lib" | sed 1,1d)
310+
for dep in "${dependencies[@]}"; do
311+
if test "$(dirname "$dep")" = "$(dirname "$PREFIX/lib/.")"; then
312+
installname="@rpath/$(basename "$dep")"
313+
install_name_tool -change "$dep" "$installname" "$lib"
314+
fi
315+
done
316+
done
317+
fi
318+
319+
cd "${DESTDIR}${PREFIX}/bin"
320+
wrapper_cmd=opal_wrapper
321+
wrapper_bin="$WORKDIR/$wrapper_cmd"
322+
wrapper_src="$PROJECT/cibw-ompi-wrapper.c"
323+
cc -DWRAPPER="$wrapper_cmd" "$wrapper_src" -o "$wrapper_bin"
324+
executables=(mpicc mpicxx mpiCC mpic++)
325+
for exe in "${executables[@]}"; do
326+
install "$wrapper_bin" "$exe"
327+
done
328+
329+
cd "${DESTDIR}${PREFIX}/bin"
330+
wrapper_cmd=orun_wrapper
331+
wrapper_bin="$WORKDIR/$wrapper_cmd"
332+
wrapper_src="$PROJECT/cibw-ompi-wrapper.c"
333+
cc -DWRAPPER="$wrapper_cmd" "$wrapper_src" -o "$wrapper_bin"
334+
cp -a mpirun "$wrapper_cmd"
335+
executables=(mpirun mpiexec)
336+
for exe in "${executables[@]}"; do
337+
install "$wrapper_bin" "$exe"
338+
done
339+
340+
} # fixup-openmpi()
341+
173342
echo fixing install tree
174343
fixup-"$mpiname"

cibw-check-mpi.sh

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
mpiname="${MPINAME:-mpich}"
4+
pkgname=$(pip list | awk '/mpich|openmpi/ {print $1}')
5+
mpiname=${pkgname%_*}
56

67
tempdir="$(mktemp -d)"
78
trap 'rm -rf $tempdir' EXIT
@@ -27,6 +28,15 @@ int main(int argc, char *argv[])
2728
EOF
2829
ln -s helloworld.c helloworld.cxx
2930

31+
if test "$mpiname" = "openmpi"; then
32+
export OMPI_ALLOW_RUN_AS_ROOT=1
33+
export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
34+
export OMPI_MCA_rmaps_base_oversubscribe=true
35+
export OMPI_MCA_rmaps_default_mapping_policy=:oversubscribe
36+
export OMPI_MCA_plm_rsh_agent=false
37+
export OMPI_MCA_plm_ssh_agent=false
38+
fi
39+
3040
RUN() { echo + "$@"; "$@"; }
3141

3242
if test "$mpiname" = "mpich"; then

0 commit comments

Comments
 (0)