Skip to content

Commit e0a74bd

Browse files
Add switches --mpi and --no-mpi to openpmd-pipe (#1336)
* Add switches --mpi and --no-mpi to openpmd-pipe * Fix order of MPI checking
1 parent a167195 commit e0a74bd

File tree

1 file changed

+54
-32
lines changed

1 file changed

+54
-32
lines changed

src/binding/python/openpmd_api/pipe/__main__.py

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,6 @@
1414

1515
from .. import openpmd_api_cxx as io
1616

17-
# MPI is an optional dependency
18-
if io.variants['mpi']:
19-
try:
20-
from mpi4py import MPI
21-
HAVE_MPI = True
22-
except (ImportError, ModuleNotFoundError):
23-
print("""
24-
openPMD-api was built with support for MPI,
25-
but mpi4py Python package was not found.
26-
Will continue in serial mode.""",
27-
file=sys.stderr)
28-
HAVE_MPI = False
29-
else:
30-
HAVE_MPI = False
31-
32-
debug = False
33-
34-
35-
class FallbackMPICommunicator:
36-
def __init__(self):
37-
self.size = 1
38-
self.rank = 0
39-
4017

4118
def parse_args(program_name):
4219
parser = argparse.ArgumentParser(
@@ -51,8 +28,19 @@ def parse_args(program_name):
5128
or multiplexing the data path in streaming setups.
5229
Parallelization with MPI is optionally possible and is done automatically
5330
as soon as the mpi4py package is found and this tool is called in an MPI
54-
context. In that case, each dataset will be equally sliced along the dimension
55-
with the largest extent.
31+
context.
32+
Parallelization with MPI is optionally possible and can be switched on with
33+
the --mpi switch, resp. switched off with the --no-mpi switch.
34+
By default, openpmd-pipe will use MPI if all of the following conditions
35+
are fulfilled:
36+
1) The mpi4py package can be imported.
37+
2) The openPMD-api has been built with support for MPI.
38+
3) The MPI size is greater than 1.
39+
By default, the openPMD-api will be initialized without an MPI communicator
40+
if the MPI size is 1. This is to simplify the use of the JSON backend
41+
which is only available in serial openPMD.
42+
With parallelization enabled, each dataset will be equally sliced along
43+
the dimension with the largest extent.
5644
5745
Examples:
5846
{0} --infile simData.h5 --outfile simData_%T.bp
@@ -72,10 +60,45 @@ def parse_args(program_name):
7260
type=str,
7361
default='{}',
7462
help='JSON config for the out file')
63+
# MPI, default: Import mpi4py if available and openPMD is parallel,
64+
# but don't use if MPI size is 1 (this makes it easier to interact with
65+
# JSON, since that backend is unavailable in parallel)
66+
if io.variants['mpi']:
67+
parser.add_argument('--mpi', action='store_true')
68+
parser.add_argument('--no-mpi', dest='mpi', action='store_false')
69+
parser.set_defaults(mpi=None)
7570

7671
return parser.parse_args()
7772

7873

74+
args = parse_args(sys.argv[0])
75+
# MPI is an optional dependency
76+
if io.variants['mpi'] and (args.mpi is None or args.mpi):
77+
try:
78+
from mpi4py import MPI
79+
HAVE_MPI = True
80+
except (ImportError, ModuleNotFoundError):
81+
if args.mpi:
82+
raise
83+
else:
84+
print("""
85+
openPMD-api was built with support for MPI,
86+
but mpi4py Python package was not found.
87+
Will continue in serial mode.""",
88+
file=sys.stderr)
89+
HAVE_MPI = False
90+
else:
91+
HAVE_MPI = False
92+
93+
debug = False
94+
95+
96+
class FallbackMPICommunicator:
97+
def __init__(self):
98+
self.size = 1
99+
self.rank = 0
100+
101+
79102
class Chunk:
80103
"""
81104
A Chunk is an n-dimensional hypercube, defined by an offset and an extent.
@@ -178,7 +201,7 @@ def __init__(self, infile, outfile, inconfig, outconfig, comm):
178201
self.comm = comm
179202

180203
def run(self):
181-
if self.comm.size == 1:
204+
if not HAVE_MPI or (args.mpi is None and self.comm.size == 1):
182205
print("Opening data source")
183206
sys.stdout.flush()
184207
inseries = io.Series(self.infile, io.Access.read_only,
@@ -320,16 +343,15 @@ def __copy(self, src, dest, current_path="/data/"):
320343

321344

322345
def main():
323-
args = parse_args(sys.argv[0])
324346
if not args.infile or not args.outfile:
325347
print("Please specify parameters --infile and --outfile.")
326348
sys.exit(1)
327-
if (HAVE_MPI):
328-
run_pipe = pipe(args.infile, args.outfile, args.inconfig,
329-
args.outconfig, MPI.COMM_WORLD)
349+
if HAVE_MPI:
350+
communicator = MPI.COMM_WORLD
330351
else:
331-
run_pipe = pipe(args.infile, args.outfile, args.inconfig,
332-
args.outconfig, FallbackMPICommunicator())
352+
communicator = FallbackMPICommunicator()
353+
run_pipe = pipe(args.infile, args.outfile, args.inconfig, args.outconfig,
354+
communicator)
333355

334356
run_pipe.run()
335357

0 commit comments

Comments
 (0)