solprop.backends.node_chunk#
How many nodes a response pass holds at once: the backend’s node-chunk plan.
A response pass synthesises the field at a chunk of the transform’s nodes, evaluates
the responses there and projects back; the chunk bounds the space-domain buffers. It is
an execution choice, not part of the scientific problem (SEP 47 sections 4.3 and 6.5):
two runs that differ only in their chunks compute the same fields to rounding, which
the chunked rows of tests/data/convergence/spatial_accuracy.json assert. So the
translation records none, and each backend plans its chunk when it is prepared, from the
problem and its ExecutionOptions
(plan_node_chunk()).
The rule is the one the translation applied before SEP 47 moved it here, so that every default and every explicit budget chooses the chunk it chose then:
The budget. An explicit
node_budgetis authoritative; without one a free-space, line or planar problem takesDEFAULT_SPATIAL_NODE_BUDGETand every otherDEFAULT_NODE_BUDGET.The base chunk. A modal or radial node holds
BUFFERS_PER_NODEcomplex temporal columns per component; a Cartesian or planar column holdsFREE_COLUMN_BUFFERS. A mode-averaged run has one node, and a general modal guide’s static matrices are a placeholder of one (its route sizes its own chunk fromgeneral_node_chunk()at the same budget).The response admissions then shrink the chunk until each node’s envelope plasma, Raman, dispersive and held-current buffers fit the same budget, refusing a budget that cannot hold one node (or one planar row), and the last step spreads the nodes evenly over the passes the admitted chunk needs.
The counts are conservative inventories, not the live buffers of each route: SEP 28’s phase 0 found the twenty Cartesian column-equivalents about three times the live group buffers (solprop issue #349). They stay, so that a user’s budget keeps buying the chunk it bought before; counting a route’s live buffers changes the chunk of every explicit budget, which is the maintainer’s decision under #349 and #89, not this move’s.
A device backend may choose differently when no budget is given (solprop issue #361);
the native backend’s rule is solprop_native.backend.device_node_chunk, and an
explicit budget or chunk is never overridden by it.
Module Attributes
Bytes of node-chunk buffers a problem may hold, before the chunk size is reduced. |
|
Node-chunk bytes a free-space, line or planar problem may hold by default (SEP 28). |
|
Node-chunk buffers the fused pass holds: |
|
Chunk buffers the general source holds per node, each |
|
Chunk buffers the general source holds per node, each |
|
Complex-equivalent buffers per component a Cartesian or planar column holds. |
|
Where a plan's chunk came from: the default budget, an explicit one, or a chunk. |
Functions
|
Return the node budget a problem takes when none is given. |
|
Return the buffers per node and component SEP 6's dispersive response adds. |
Return the buffers per node and component SEP 6's response adds to a chunk. |
|
|
Return the nodes the general source may hold at once within a byte budget. |
|
Return the general route's node chunk under a backend's node-chunk plan. |
|
Plan a problem's node chunk on the host rule, before anything is allocated. |
Classes
|
A backend's node chunk and what chose it, recorded as execution metadata. |
- solprop.backends.node_chunk.BUFFERS_PER_GENERAL_NODE = 4#
Chunk buffers the general source holds per node, each
n_componentswide.The synthesised fine spectrum, the analytic time field, the polarisation in time and its one-sided spectrum.
- solprop.backends.node_chunk.BUFFERS_PER_NODE = 3#
Node-chunk buffers the fused pass holds:
E,Pand the Raman drive.
- solprop.backends.node_chunk.ChunkSource#
Where a plan’s chunk came from: the default budget, an explicit one, or a chunk.
alias of
Literal[‘default’, ‘explicit’, ‘forced’]
- solprop.backends.node_chunk.DEFAULT_NODE_BUDGET = 67108864#
Bytes of node-chunk buffers a problem may hold, before the chunk size is reduced.
Architecture section 13 chooses the whole node set when it fits a per-problem budget and the largest chunk that fits otherwise. Sixty-four mebibytes reproduces the chunk of about sixteen nodes that section 8 tabulates for the comb-to-continuum target (32768 time samples, six modes, Raman) while leaving a small problem un-chunked. It is an estimate until the benchmark suite measures the crossover.
The free-space, line and planar grids default to
DEFAULT_SPATIAL_NODE_BUDGET.
- solprop.backends.node_chunk.DEFAULT_SPATIAL_NODE_BUDGET = 1073741824#
Node-chunk bytes a free-space, line or planar problem may hold by default (SEP 28).
A spatial evaluation pays a fixed cost per node chunk: its launches, its temporal transforms’ thread wake-ups, and its gather and scatter. A field volume is gigabytes, so a larger group is cheap in memory. With the per-chunk copies and clears removed, one gibibyte was the fastest of 64, 256 and 1024 MiB for the 384- and 768-square Kerr beams on Zen 5 and on Apple silicon, 2.3 to 2.4 times faster than 64 MiB on the native backend’s march; on an H200, IP-DOPRI5 was 1.3 times faster at one gibibyte than at 64 MiB.
- solprop.backends.node_chunk.FREE_COLUMN_BUFFERS = 20#
Complex-equivalent buffers per component a Cartesian or planar column holds.
Eight response and FFT buffers, three doubled Raman buffers, 3.5 device plasma buffers, two split-step buffers and 2.5 statistic buffers: 19, and one more column for the real FFT’s endpoint bins. The transverse scratch and the opaque FFT plans are named separately in the memory ledgers. A conservative inventory, about three times the live group buffers (solprop issue #349); the dispersive admission adds its own to it.
- class solprop.backends.node_chunk.NodeChunkPlan(chunk, budget, source, requested=None)[source]#
Bases:
objectA backend’s node chunk and what chose it, recorded as execution metadata.
- Attributes:
- chunkint
Nodes a response pass holds at once, between 1 and the transform’s node count; one on a general modal guide, whose static matrices are a placeholder.
- budgetint
The budget the chunk was planned within, bytes: the explicit one, or the problem’s default (
default_node_budget()).- source{‘default’, ‘explicit’, ‘forced’}
"default"without an explicit budget (the route’s default budget),"explicit"with one, and"forced"for an exact chunk (solprop.backends.session.ExecutionOptions.node_chunk).- requestedint or None
The exact chunk asked for, before it was bounded by the node count;
Noneunless source is"forced". A general modal guide’s route takes it in place of its own budgeted chunk.
Examples
>>> from solprop.backends.node_chunk import NodeChunkPlan >>> NodeChunkPlan(16, 2**26, "default").record() {'node_chunk': 16, 'node_budget': 67108864, 'node_chunk_source': 'default'}
- property automatic: bool[source]#
Whether no budget or chunk was given, so a machine rule may apply.
Truewhen source is"default".
- solprop.backends.node_chunk.PAIR_BUFFERS_PER_GENERAL_NODE = 2#
Chunk buffers the general source holds per node, each
n_componentssquared.The tensor contraction is written in two steps rather than as one four-operand
einsum, so that every intermediate it allocates is a buffer this module names: the pair historyE_k conj(E_l)and the tensor contracted against it. A singleeinsumwithoptimize=Trueallocates the same intermediates and names none of them, which a memory ledger cannot report.The static maps
SandQ, the per-node tensor, the dense E/H reference, its reciprocal partners and the coefficient dual are whole-problem allocations, counted row by row bysolprop.backends.numpy_ref.general_modal.general_memory(); they do not shrink with the chunk, which is why the counts here andBUFFERS_PER_NODEare different and neither reuses the other.
- solprop.backends.node_chunk.default_node_budget(transform)[source]#
Return the node budget a problem takes when none is given.
- Parameters:
- transformsolprop.translate.modal.Transform
The problem’s transform.
- Returns:
- int
DEFAULT_SPATIAL_NODE_BUDGETon a Cartesian (free-space or line) or planar transform,DEFAULT_NODE_BUDGETotherwise.
- solprop.backends.node_chunk.dispersive_node_buffers(responses, *, spatial)[source]#
Return the buffers per node and component SEP 6’s dispersive response adds.
On the fused node path a backend forms the response’s products at the nodes: one node buffer beside other responses for the symmetric evaluator, which a lone one shares with the bare field, and two for the polynomial, whose cube and derivative products take them in turn. A Cartesian or planar column also holds its filtered fields and products in time and their spectra: two buffers per product, the symmetric evaluator’s one (a mixture’s under its mixture filter) and the polynomial’s
1 + 2 GforGgroups of equal leg bound (groups()), and the planar nodes’ one or two besides.- Parameters:
- responsessolprop.translate.responses.CompiledResponses
The compiled responses, with or without the dispersive leaf.
- spatialbool
Whether the route’s nodes are Cartesian or planar columns.
- Returns:
- int
Complex-equivalent buffers per node and component; zero without the leaf.
- solprop.backends.node_chunk.general_dispersive_buffers(leaf)[source]#
Return the buffers per node and component SEP 6’s response adds to a chunk.
The compiled general workspace holds, for each node of a chunk and each of its components, every filtered field’s spectrum and time series and every product and its spectrum: two complex-equivalent buffers per field and two per product. The symmetric evaluator has one field and one product per region with a gas fill (a mixture’s under its mixture filter); the polynomial two fields and two products per group of equal leg bound, and one cube per region (
groups()).- Parameters:
- leafsolprop.translate.responses.DispersiveKerrTerms or None
The route’s dispersive channels, or
None.
- Returns:
- int
Complex-equivalent buffers per node and component; zero without the leaf.
- solprop.backends.node_chunk.general_node_chunk(n_components, n_to, n_omega_fine, budget, *, dispersive=0)[source]#
Return the nodes the general source may hold at once within a byte budget.
The chunk bounds the space-domain work alone:
BUFFERS_PER_GENERAL_NODEcomplex buffers per node and component,PAIR_BUFFERS_PER_GENERAL_NODEper node and component squared, and SEP 6’s dispersive response’s own (general_dispersive_buffers()), over the longer of the fine time axis and the fine spectrum. The maps, the reference and the dual are whole-problem allocations that no chunk shrinks (solprop.backends.numpy_ref.general_modal.general_memory()).- Parameters:
- n_componentsint
Cartesian components of the local field, positive.
- n_toint
Fine time samples, positive.
- n_omega_fineint
Fine spectral bins, positive.
- budgetint
Bytes the chunk buffers may occupy in total, positive.
- dispersiveint, optional
The dispersive response’s complex buffers per node and component; zero, the default, without one.
- Returns:
- int
The chunk size, at least one.
- Raises:
- BackendError
If the budget is not positive.
Examples
>>> from solprop.backends.node_chunk import general_node_chunk >>> general_node_chunk(3, 1024, 513, 64 * 2**20) 136
- solprop.backends.node_chunk.general_planned_chunk(problem, plan)[source]#
Return the general route’s node chunk under a backend’s node-chunk plan.
The route’s own rule (
general_node_chunk()) within the plan’s budget – the explicit one, orDEFAULT_NODE_BUDGET– or the plan’s exact chunk when one was forced, bounded by the node count. Both compiled backends take it, so that they execute the same chunks.- Parameters:
- problemsolprop.translate.problem.PropagationProblem
A problem that carries
transform.modal_tables.- plansolprop.backends.node_chunk.NodeChunkPlan
The backend’s plan (
solprop.backends.node_chunk.plan_node_chunk()).
- Returns:
- int
Nodes the general source holds at once, between one and the node count.
- solprop.backends.node_chunk.plan_node_chunk(problem, options=None)[source]#
Plan a problem’s node chunk on the host rule, before anything is allocated.
- Parameters:
- problemsolprop.translate.problem.PropagationProblem
The validated problem.
- optionssolprop.backends.session.ExecutionOptions or None, optional
The run’s execution options;
Nonefor the defaults.
- Returns:
- NodeChunkPlan
The chunk, its budget and its source.
- Raises:
- solprop.exceptions.BackendError
If the budget cannot hold one node’s buffers (one complete temporal column, or one planar transverse row, with every response’s own).
Examples
>>> from solprop.grid import EnvelopeGrid >>> from solprop.nonlinear.gnlse import problem_from >>> from solprop.pulses import SechPulse >>> from solprop.stepper import PIController >>> from solprop.translate.problem import assemble >>> from solprop.backends.node_chunk import plan_node_chunk >>> grid = EnvelopeGrid.from_limits(0.01, 835e-9, (500e-9, 2e-6), 1e-12) >>> gnlse = problem_from([0.0, 0.0, -1.2e-26], omega_ref=grid.omega0, gamma=0.11) >>> start = SechPulse(wavelength=835e-9, width=1e-13, peak_power=1.0).build(grid) >>> problem, request = assemble(grid, gnlse.mode, [gnlse.kerr], start, ... controller=PIController(rtol=1e-8, atol=1e-14), ... save_planes=[0.01], dz_max=0.01, dz_init=1e-3, ... density=1.0, shock=False, prefactor_index=1.0) >>> plan_node_chunk(problem).chunk 1