Skip to content

simulator.shared

The large arrays of a chunk result in shared memory, from a worker to the parent.

A worker of a pool returns the result of a chunk through a pipe of the pool, which pickles its arrays in the worker and unpickles them in the parent: 8 results of 214 MB take 1.44 s on linux with 4 workers, 0.11 s written into shared memory. A worker therefore writes an array of at least SHARED_MEMORY_THRESHOLD bytes into a segment of multiprocessing.shared_memory which it creates (share) and returns its SharedArray, the name, the shape and the dtype, instead of the array; the parent maps the segment, removes its name and reads the array from the mapping, without a copy, which is released with the array (receive). A smaller array keeps pickling, a segment costs more than it saves.

The parent owns the segments of a run: their names are a prefix of the run (run_prefix) and the position of the chunk (segment_stem), and a worker creates a segment without the resource tracker (track=False), which would remove it when the worker ends, before the parent read it. The parent removes the name of every segment it reads and, at the end of the run, also after an error, Ctrl-C or a dead worker, every name of the run which may exist (unlink), so no segment outlives its run. A run in the calling process never uses segments.

Shared memory is used on POSIX only (linux, macOS): on windows a named mapping disappears when its last handle closes, so a worker cannot hand one over after it returned, and the arrays keep pickling there. An array keeps pickling as well when its segment cannot be created or its memory reserved, e.g. a /dev/shm too small for it.

SharedArray dataclass

SharedArray(name, shape, dtype)

An array in a segment of shared memory, see share.

Attributes:

Name Type Description
name str

the name of the segment.

shape tuple[int, ...]

the shape of the array.

dtype str

the dtype of the array, as numpy.dtype.str.

supported

supported()

Whether arrays are handed over in shared memory, on POSIX only.

run_prefix

run_prefix()

Get a new prefix of the names of the segments of a run.

It is short, since macOS limits the name of a segment to 31 characters with its leading slash.

segment_stem

segment_stem(prefix, chunk)

Get the stem of the names of the segments of a chunk of a run.

The segment of an array of the chunk is the stem and one of SUFFIXES.

Parameters:

Name Type Description Default
prefix str

the prefix of the run, see run_prefix.

required
chunk int

the position of the chunk in the run.

required

segment_names

segment_names(stem)

Get the name of every segment a chunk of this stem may create.

share

share(array, name)

Write an array into a new segment of shared memory, if it is worth it.

Parameters:

Name Type Description Default
array ndarray

the array.

required
name str

the name of the segment.

required

Returns:

Type Description
ndarray | SharedArray

The SharedArray of the segment, or the array itself when it is

ndarray | SharedArray

smaller than SHARED_MEMORY_THRESHOLD, shared memory is not

ndarray | SharedArray

supported or the segment cannot be created.

receive

receive(shared)

Get an array from its segment, whose name is removed.

The array is a read-only view on the memory of the segment, mapped into the process, which is released with the last reference to the array: no copy, and nothing to close. The segment is mapped without SharedMemory, which must be closed explicitly and cannot be closed while a view on it exists.

Parameters:

Name Type Description Default
shared SharedArray

the array in its segment.

required

Returns:

Type Description
ndarray

The array.

unlink(names)

Remove the segments of these names which exist.

Parameters:

Name Type Description Default
names Iterable[str]

the names of segments which may exist.

required