Skip to content

Commit 5110b82

Browse files
committed
improves heuristic in default implementation of GridIndex._chunk_io
This commit improves the heuristic used by `GridIndex`’s default implementation of the `_chunk_io` method (with the `"auto"` chunk-sizing strategy) for determining how many grids to read in a given iteration. For context, the heuristic was historically hardcoded to a value of 1000 grids. This works well for AMR simulations with small grids (e.g. 16^3, 32^3), but the heuristic is problematic when you have unified skmulations This commit adopts a heuristic that tries to limit the number of grids in order to make sure we don't run out of memory.
1 parent 0ba2cfa commit 5110b82

1 file changed

Lines changed: 28 additions & 3 deletions

File tree

yt/geometry/grid_geometry_handler.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import abc
22
import weakref
33
from collections import defaultdict
4+
from functools import cached_property
45

56
import numpy as np
67

@@ -387,7 +388,10 @@ def _chunk_spatial(self, dobj, ngz, sort=None, preload_fields=None):
387388
# individual grids.
388389
yield YTDataChunk(dobj, "spatial", [g], size, cache=False)
389390

390-
_grid_chunksize = 1000
391+
@cached_property
392+
def _max_grid_cell_count(self):
393+
"""Returns the max number of cells in a grid"""
394+
return self.grid_dimensions.prod(axis=1).max()
391395

392396
def _chunk_io(
393397
self,
@@ -413,11 +417,32 @@ def _chunk_io(
413417
if chunk_sizing == "auto":
414418
chunk_ngrids = len(gobjs)
415419
if chunk_ngrids > 0:
420+
# historically, we hardcoded `_grid_chunksize` to 1000. For context,
421+
# `_grid_chunksize` is the number of grids for this object to load
422+
# (assuming no parallelism). While this heuristic works well with
423+
# small AMR grids (e.g. 16^3 or 32^3 cells), this was problematic with
424+
# uniform resolution snapshots (e.g. Cholla snapshots commonly have
425+
# 256^3 cells per grid)
426+
#
427+
# Our current heuristic picks a `_grid_chunksize` of 1 or a value such
428+
# that holding arrays for `_field_count` fields in memory at once will
429+
# never take up more than `_max_num_bytes`
430+
_field_count = 10 # an arbitrary value
431+
_max_num_bytes = int(1e9) # another arbitrary value
432+
433+
# if we assume double-precision field values, then a field array for
434+
# single grid requires up to the following number of bytes
435+
_bytes_per_field_per_grid = 8 * int(self._max_grid_cell_count)
436+
437+
_grid_chunksize = max(
438+
_max_num_bytes // (_bytes_per_field_per_grid * _field_count), 1
439+
)
440+
416441
nproc = int(ytcfg.get("yt", "internals", "global_parallel_size"))
417442
chunking_factor = np.int64(
418-
np.ceil(self._grid_chunksize * nproc / chunk_ngrids)
443+
np.ceil(_grid_chunksize * nproc / chunk_ngrids)
419444
)
420-
size = max(self._grid_chunksize // chunking_factor, 1)
445+
size = max(_grid_chunksize // chunking_factor, 1)
421446
else:
422447
size = self._grid_chunksize
423448
elif chunk_sizing == "config_file":

0 commit comments

Comments
 (0)