Skip to content

Commit 3294158

Browse files
authored
Merge pull request #2130 from devitocodes/mpi0_logging
misc: Add MPI0 logging level
2 parents 8729cd2 + e459d52 commit 3294158

File tree

4 files changed

+32
-10
lines changed

4 files changed

+32
-10
lines changed

FAQ.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -596,9 +596,9 @@ By default, Devito compiles the generated code using flags that maximize the run
596596

597597
[top](#Frequently-Asked-Questions)
598598

599-
## Can I control the MPI domain decomposition
599+
## Can I control the MPI domain decomposition?
600600

601-
Until Devito v3.5 included, domain decomposition occurs along the fastest axis. As of later versions, domain decomposition occurs along the slowest axis, for performance reasons. And yes, it is possible to control the domain decomposition in user code, but this is not neatly documented. Take a look at `test_custom_topology` in [this file](https://github.com/devitocodes/devito/blob/master/tests/test_mpi.py). In essence, `Grid` accepts the optional argument `topology`, which allows the user to pass a custom topology as an n-tuple, where `n` is the number of distributed dimensions. For example, for a two-dimensional grid, the topology `(4, 1)` will decompose the slowest axis into four partitions, one partition per MPI rank, while the fastest axis will be replicated over all MPI ranks.
601+
Until Devito v3.5 included, domain decomposition occurs along the fastest axis. As of later versions, domain decomposition occurs along the slowest axis, for performance reasons. And yes, it is possible to control the domain decomposition in user code, but this is not neatly documented. Take a look at `class CustomTopology` in [distributed.py](https://github.com/devitocodes/devito/blob/master/devito/mpi/distributed.py) and `test_custom_topology` in [this file](https://github.com/devitocodes/devito/blob/master/tests/test_mpi.py). In essence, `Grid` accepts the optional argument `topology`, which allows the user to pass a custom topology as an n-tuple, where `n` is the number of distributed dimensions. For example, for a two-dimensional grid, the topology `(4, 1)` will decompose the slowest axis into four partitions, one partition per MPI rank, while the fastest axis will be replicated over all MPI ranks.
602602

603603

604604
[top](#Frequently-Asked-Questions)

devito/logger.py

+25-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import sys
55
from contextlib import contextmanager
66

7-
__all__ = ('set_log_level', 'set_log_noperf', 'is_log_enabled_for',
7+
__all__ = ('set_log_level', 'set_log_noperf', 'is_log_enabled_for', 'switch_log_level',
88
'log', 'warning', 'error', 'perf', 'hint',
99
'RED', 'GREEN', 'BLUE')
1010

@@ -71,21 +71,42 @@ def set_log_level(level, comm=None):
7171
comm : MPI communicator, optional
7272
An MPI communicator the logger should be collective over. If provided, only
7373
rank-0 on that communicator will write to the registered handlers, other
74-
ranks will use a `logging.NullHandler`. By default, ``comm`` is set
75-
to ``None``, so all ranks will use the default handlers. This could be
74+
ranks will use a `logging.NullHandler`. By default, ``comm`` is set
75+
to ``None``, so all ranks will use the default handlers. This could be
7676
used, for example, if one wants to log to one file per rank.
7777
"""
7878
from devito import configuration
7979

80-
if comm is not None:
80+
if comm is not None and configuration['mpi']:
8181
if comm.rank != 0:
8282
logger.removeHandler(stream_handler)
8383
logger.addHandler(logging.NullHandler())
84+
else:
85+
logger.addHandler(stream_handler)
8486

8587
# Triggers a callback to `_set_log_level`
8688
configuration['log-level'] = level
8789

8890

91+
class switch_log_level(object):
92+
"""
93+
A context manager to temporarily change MPI logging.
94+
"""
95+
96+
def __init__(self, comm):
97+
98+
from devito import configuration
99+
self.level = configuration['log-level']
100+
self.comm = comm
101+
102+
def __enter__(self):
103+
# Limit logging to rank 0
104+
set_log_level(self.level, self.comm)
105+
106+
def __exit__(self, *args):
107+
set_log_level(self.level)
108+
109+
89110
def set_log_noperf():
90111
"""Do not print performance-related messages."""
91112
logger.setLevel(WARNING)

devito/operator/operator.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from devito.arch import compiler_registry, platform_registry
1010
from devito.data import default_allocator
1111
from devito.exceptions import InvalidOperator, ExecutionError
12-
from devito.logger import debug, info, perf, warning, is_log_enabled_for
12+
from devito.logger import debug, info, perf, warning, is_log_enabled_for, switch_log_level
1313
from devito.ir.equations import LoweredEq, lower_exprs
1414
from devito.ir.clusters import ClusterGroup, clusterize
1515
from devito.ir.iet import (Callable, CInterface, EntryFunction, FindSymbols, MetaCall,
@@ -871,8 +871,9 @@ def apply(self, **kwargs):
871871
# Post-process runtime arguments
872872
self._postprocess_arguments(args, **kwargs)
873873

874-
# Output summary of performance achieved
875-
return self._emit_apply_profiling(args)
874+
# In case MPI is used restrict result logging to one rank only
875+
with switch_log_level(comm=args.comm):
876+
return self._emit_apply_profiling(args)
876877

877878
# Performance profiling
878879

devito/operator/profiling.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ def add_glb_vanilla(self, key, time):
473473
ops = sum(v.ops for v in self.input.values())
474474
traffic = sum(v.traffic for v in self.input.values())
475475

476-
if np.isnan(traffic):
476+
if np.isnan(traffic) or traffic == 0:
477477
return
478478

479479
gflops = float(ops)/10**9

0 commit comments

Comments
 (0)