Skip to content

Commit 10d95b2

Browse files
authored
Merge pull request #99 from altheaden/make-cell-count-heuristic
Make cell count heuristic
2 parents 76c6700 + 9abf4b9 commit 10d95b2

File tree

10 files changed

+48
-123
lines changed

10 files changed

+48
-123
lines changed

docs/developers_guide/ocean/framework.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ respectively) are set automatically if `ntasks` and `min_tasks` have not
4444
already been set explicitly. In such cases, a subclass of `OceanModelStep`
4545
must override the
4646
{py:meth}`polaris.ocean.model.OceanModelStep.compute_cell_count()` method
47-
to compute the number of cells in the mesh. Since it is typically not possible
48-
to read the cell count from a file during setup, this method may need to have
49-
a heuristic way of approximating the number of cells during setup (i.e. when
50-
the `at_setup` parameter is `True`. Then, it can return the exact number of
51-
cells at runtime (i.e. `at_setup == False`).
47+
to approximate the number of cells in the mesh, using a simple heuristic.
5248

5349
The algorithm for determining the resources is:
5450

docs/developers_guide/ocean/test_groups/baroclinic_channel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ constructor, the associate namelist option (`config_mom_del2`) will be given
5353
this value. Namelist and streams files are updated in
5454
{py:meth}`polaris.ocean.tests.baroclinic_channel.forward.Forward.dynamic_model_config()`
5555
with time steps determined algorithmically based on config options. The
56-
number of cells is computed from config options in
56+
number of cells is approximated from config options in
5757
{py:meth}`polaris.ocean.tests.baroclinic_channel.forward.Forward.compute_cell_count()`
5858
so that this can be used to constrain the number of MPI tasks that tests
5959
have as their target and minimum (if the resources are not explicitly

docs/developers_guide/ocean/test_groups/inertial_gravity_wave.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ defines a step for running MPAS-Ocean from the initial condition produced in the
5050
`init` step. Namelist and streams files are updated in
5151
{py:meth}`polaris.ocean.tests.inertial_gravity_wave.forward.Forward.dynamic_model_config()`
5252
with time steps determined algorithmically based on config options. The number
53-
of cells is computed from config options in
53+
of cells is approximated from config options in
5454
{py:meth}`polaris.ocean.tests.inertial_gravity_wave.forward.Forward.compute_cell_count()`
5555
so that this can be used to constrain the number of MPI tasks that tests have as
5656
their target and minimum (if the resources are not explicitly prescribed). For

docs/developers_guide/ocean/test_groups/manufactured_solution.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ defines a step for running MPAS-Ocean from the initial condition produced in
5050
the `init` step. Namelist and streams files are updated in
5151
{py:meth}`polaris.ocean.tests.manufactured_solution.forward.Forward.dynamic_model_config()`
5252
with time steps determined algorithmically based on config options. The
53-
number of cells is computed from config options in
53+
number of cells is approximated from config options in
5454
{py:meth}`polaris.ocean.tests.manufactured_solution.forward.Forward.compute_cell_count()`
5555
so that this can be used to constrain the number of MPI tasks that tests
5656
have as their target and minimum (if the resources are not explicitly

docs/tutorials/dev_add_test_group.md

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ you might try to stress-test your own test case.
11801180

11811181
## Adding the forward step
11821182

1183-
Now that we know that the first step steems to be working, we're ready to add
1183+
Now that we know that the first step seems to be working, we're ready to add
11841184
another. We will add a `forward` step for running the MPAS-Ocean model forward
11851185
in time from the initial condition created in `init`. `forward`
11861186
will be a little more complicated than `init` as we get started.
@@ -2022,16 +2022,15 @@ dt_per_km = 30
20222022
btr_dt_per_km = 1.5
20232023
```
20242024
2025-
Unlike in `compute_cell_count()`, we don't do anything differently in
2026-
`dynamic_model_config()` here whether it's run at setup or at runtime. The
2027-
reason we run it twice is to update the model config options in case the user
2028-
modified `dt_per_km` or `btr_dt_per_km` in the config file in the work
2029-
directory before running the step.
2025+
We don't do anything differently in `dynamic_model_config()` here whether it's
2026+
run at setup or at runtime. The reason we run it twice is to update the model
2027+
config options in case the user modified `dt_per_km` or `btr_dt_per_km` in the
2028+
config file in the work directory before running the step.
20302029
20312030
### Computing the cell count
20322031
20332032
In the ocean component, we have infrastructure for determining good values
2034-
for `ntask` and `min_tasks` (the reasonable range of MPI tasks that a forward
2033+
for `ntasks` and `min_tasks` (the reasonable range of MPI tasks that a forward
20352034
model step should use). Using this infrastructure requires overriding the
20362035
{py:meth}`polaris.ocean.model.OceanModelStep.compute_cell_count()` method:
20372036
@@ -2045,7 +2044,7 @@ class Forward(OceanModelStep):
20452044
20462045
...
20472046
2048-
def compute_cell_count(self, at_setup):
2047+
def compute_cell_count(self):
20492048
"""
20502049
Compute the approximate number of cells in the mesh, used to constrain
20512050
resources
@@ -2061,32 +2060,21 @@ class Forward(OceanModelStep):
20612060
cell_count : int or None
20622061
The approximate number of cells in the mesh
20632062
"""
2064-
if at_setup:
2065-
# no file to read from, so we'll compute it based on config options
2066-
section = self.config['yet_another_channel']
2067-
lx = section.getfloat('lx')
2068-
ly = section.getfloat('ly')
2069-
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
2070-
cell_count = nx * ny
2071-
else:
2072-
# get nCells from the input file
2073-
with xr.open_dataset('initial_state.nc') as ds:
2074-
cell_count = ds.sizes['nCells']
2063+
section = self.config['yet_another_channel']
2064+
lx = section.getfloat('lx')
2065+
ly = section.getfloat('ly')
2066+
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
2067+
cell_count = nx * ny
20752068
return cell_count
20762069
```
2077-
This method gets called once at setup (with `at_setup=True`) and once at
2078-
runtime (with `at_setup=False`). We do this because we need to compute or
2079-
estimate the size of the mesh during setup so we have a good guess at the
2070+
We need to estimate the size of the mesh so we have a good guess at the
20802071
resources it will need when we add it to a test suite and make a job script for
2081-
running it. Then, at runtime, we may need to revise that size, either because
2082-
it was an estimate only or because it was based on config options that a user
2083-
may have changed after setup. Here, we use
2072+
running it. Here, we use
20842073
{py:func}`polaris.mesh.planar.compute_planar_hex_nx_ny()` to get `nx` and `ny`
20852074
(and thus the total cell count) during setup because we have no other way to
2086-
get them (the initial condition has not yet been created, for example). But
2087-
at runtime, rather than recomputing them, we look at the initial condition
2088-
file that must exist (otherwise the step already would have failed) to see
2089-
what the actual number of cells ended up being.
2075+
get them. When using task parallelism, we must use this approximation at
2076+
runtime, because we cannot rely on any tests being completed to use as a basis
2077+
for computation.
20902078
20912079
`cell_count` is used in `OceanModelStep` to compute `ntasks` and `min_tasks`
20922080
by also using 2 config options:

polaris/ocean/model/ocean_model_step.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def setup(self):
102102
self.dynamic_ntasks = (self.ntasks is None and self.min_tasks is None)
103103

104104
if self.dynamic_ntasks:
105-
self._update_ntasks(at_setup=True)
105+
self._update_ntasks()
106106

107107
super().setup()
108108

@@ -111,20 +111,14 @@ def constrain_resources(self, available_cores):
111111
Update the number of MPI tasks to use based on the estimated mesh size
112112
"""
113113
if self.dynamic_ntasks:
114-
self._update_ntasks(at_setup=False)
114+
self._update_ntasks()
115115
super().constrain_resources(available_cores)
116116

117-
def compute_cell_count(self, at_setup):
117+
def compute_cell_count(self):
118118
"""
119119
Compute the approximate number of cells in the mesh, used to constrain
120120
resources
121121
122-
Parameters
123-
----------
124-
at_setup : bool
125-
Whether this method is being run during setup of the step, as
126-
opposed to at runtime
127-
128122
Returns
129123
-------
130124
cell_count : int or None
@@ -193,13 +187,13 @@ def add_streams_file(self, package, streams, template_replacements=None):
193187
raise ValueError('Input streams files are not supported in '
194188
'OceanModelStep')
195189

196-
def _update_ntasks(self, at_setup):
190+
def _update_ntasks(self):
197191
"""
198192
Update ``ntasks`` and ``min_tasks`` for the step based on the estimated
199193
mesh size
200194
"""
201195
config = self.config
202-
cell_count = self.compute_cell_count(at_setup)
196+
cell_count = self.compute_cell_count()
203197
if cell_count is None:
204198
raise ValueError('ntasks and min_tasks were not set explicitly '
205199
'but they also cannot be computed because '

polaris/ocean/tests/baroclinic_channel/forward.py

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import time
22

3-
import xarray as xr
4-
53
from polaris.mesh.planar import compute_planar_hex_nx_ny
64
from polaris.ocean.model import OceanModelStep
75

@@ -95,33 +93,21 @@ def __init__(self, test_case, resolution, name='forward', subdir=None,
9593
self.dt = None
9694
self.btr_dt = None
9795

98-
def compute_cell_count(self, at_setup):
96+
def compute_cell_count(self):
9997
"""
10098
Compute the approximate number of cells in the mesh, used to constrain
10199
resources
102100
103-
Parameters
104-
----------
105-
at_setup : bool
106-
Whether this method is being run during setup of the step, as
107-
opposed to at runtime
108-
109101
Returns
110102
-------
111103
cell_count : int or None
112104
The approximate number of cells in the mesh
113105
"""
114-
if at_setup:
115-
# no file to read from, so we'll compute it based on config options
116-
section = self.config['baroclinic_channel']
117-
lx = section.getfloat('lx')
118-
ly = section.getfloat('ly')
119-
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
120-
cell_count = nx * ny
121-
else:
122-
# get nCells from the input file
123-
with xr.open_dataset('initial_state.nc') as ds:
124-
cell_count = ds.sizes['nCells']
106+
section = self.config['baroclinic_channel']
107+
lx = section.getfloat('lx')
108+
ly = section.getfloat('ly')
109+
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
110+
cell_count = nx * ny
125111
return cell_count
126112

127113
def dynamic_model_config(self, at_setup):

polaris/ocean/tests/global_convergence/cosine_bell/forward.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import time
22

3-
import xarray as xr
4-
53
from polaris.ocean.model import OceanModelStep
64

75

@@ -55,30 +53,18 @@ def __init__(self, test_case, resolution, mesh_name):
5553

5654
self.add_output_file(filename='output.nc')
5755

58-
def compute_cell_count(self, at_setup):
56+
def compute_cell_count(self):
5957
"""
6058
Compute the approximate number of cells in the mesh, used to constrain
6159
resources
6260
63-
Parameters
64-
----------
65-
at_setup : bool
66-
Whether this method is being run during setup of the step, as
67-
opposed to at runtime
68-
6961
Returns
7062
-------
7163
cell_count : int or None
7264
The approximate number of cells in the mesh
7365
"""
74-
if at_setup:
75-
# use a heuristic based on QU30 (65275 cells) and QU240 (10383
76-
# cells)
77-
cell_count = 6e8 / self.resolution**2
78-
else:
79-
# get nCells from the input file
80-
with xr.open_dataset('init.nc') as ds:
81-
cell_count = ds.sizes['nCells']
66+
# use a heuristic based on QU30 (65275 cells) and QU240 (10383 cells)
67+
cell_count = 6e8 / self.resolution**2
8268
return cell_count
8369

8470
def dynamic_model_config(self, at_setup):

polaris/ocean/tests/inertial_gravity_wave/forward.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import time
22

33
import numpy as np
4-
import xarray as xr
54

65
from polaris.mesh.planar import compute_planar_hex_nx_ny
76
from polaris.ocean.model import OceanModelStep
@@ -61,33 +60,21 @@ def __init__(self, test_case, resolution,
6160
self.add_yaml_file('polaris.ocean.tests.inertial_gravity_wave',
6261
'forward.yaml')
6362

64-
def compute_cell_count(self, at_setup):
63+
def compute_cell_count(self):
6564
"""
6665
Compute the approximate number of cells in the mesh, used to constrain
6766
resources
6867
69-
Parameters
70-
----------
71-
at_setup : bool
72-
Whether this method is being run during setup of the step, as
73-
opposed to at runtime
74-
7568
Returns
7669
-------
7770
cell_count : int or None
7871
The approximate number of cells in the mesh
7972
"""
80-
if at_setup:
81-
# no file to read from, so we'll compute it based on config options
82-
section = self.config['inertial_gravity_wave']
83-
lx = section.getfloat('lx')
84-
ly = np.sqrt(3.0) / 2.0 * lx
85-
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
86-
cell_count = nx * ny
87-
else:
88-
# get nCells from the input file
89-
with xr.open_dataset('initial_state.nc') as ds:
90-
cell_count = ds.sizes['nCells']
73+
section = self.config['inertial_gravity_wave']
74+
lx = section.getfloat('lx')
75+
ly = np.sqrt(3.0) / 2.0 * lx
76+
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
77+
cell_count = nx * ny
9178
return cell_count
9279

9380
def dynamic_model_config(self, at_setup):

polaris/ocean/tests/manufactured_solution/forward.py

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import time
22

33
import numpy as np
4-
import xarray as xr
54

65
from polaris.mesh.planar import compute_planar_hex_nx_ny
76
from polaris.ocean.model import OceanModelStep
@@ -64,33 +63,22 @@ def __init__(self, test_case, resolution,
6463
self.add_yaml_file('polaris.ocean.tests.manufactured_solution',
6564
'forward.yaml')
6665

67-
def compute_cell_count(self, at_setup):
66+
def compute_cell_count(self):
6867
"""
6968
Compute the approximate number of cells in the mesh, used to constrain
7069
resources
7170
72-
Parameters
73-
----------
74-
at_setup : bool
75-
Whether this method is being run during setup of the step, as
76-
opposed to at runtime
77-
7871
Returns
7972
-------
8073
cell_count : int or None
8174
The approximate number of cells in the mesh
8275
"""
83-
if at_setup:
84-
# no file to read from, so we'll compute it based on config options
85-
section = self.config['manufactured_solution']
86-
lx = section.getfloat('lx')
87-
ly = np.sqrt(3.0) / 2.0 * lx
88-
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
89-
cell_count = nx * ny
90-
else:
91-
# get nCells from the input file
92-
with xr.open_dataset('initial_state.nc') as ds:
93-
cell_count = ds.sizes['nCells']
76+
# no file to read from, so we'll compute it based on config options
77+
section = self.config['manufactured_solution']
78+
lx = section.getfloat('lx')
79+
ly = np.sqrt(3.0) / 2.0 * lx
80+
nx, ny = compute_planar_hex_nx_ny(lx, ly, self.resolution)
81+
cell_count = nx * ny
9482
return cell_count
9583

9684
def dynamic_model_config(self, at_setup):

0 commit comments

Comments
 (0)