Skip to content

The node chunk is sized at translation, whatever the device, and each chunk is a kernel launch #361

Open

Description

@jtravs

What happens

A source's node chunk is sized by SimulationSettings.node_budget at translation, whatever the backend: min(n_columns, node_budget // column_bytes), with 64 MiB on modal routes and 1 GiB on spatial ones. On a device a chunk is a kernel launch.

SEP 16 measured the 128 x 128 Cartesian filament on a data-centre GPU: 161 chunks a call at the then default of 64 MiB, and with every column in one chunk IP-DOPRI5 ran 4 times faster and the exponential formulation 2.4 times.

Those numbers are out of date. The spatial default has since gone to 1 GiB. By arithmetic, not run, with column bytes 20 * 16 * n_pol * n_to and n_pol * n_to = 2048, which reproduces SEP 16's 102 columns a chunk, that case now takes 1638 columns a chunk, so 11 chunks a call. So most of that gain may already be had, and the remaining gain is unknown.

To do

  • Re-measure the filament on a data-centre GPU at the default budget and with one chunk, on Runge-Kutta and Adams, with SOLPROP_BENCH_NODE_BUDGET or the setting.
  • If it still pays, let the device backend choose its chunk from the device's memory when it is built.

Constraints: translation must not import the device runtime, since a scan must not initialise it before it forks. A chunk of any size gives the same fields to rounding, which the chunked record rows assert. An explicit node_budget must still win. #89's buffer plan should see the same number.

Needs a decision: this changes a device run's default memory use, so it is the maintainer's. I recommend it only if the re-measurement shows at least 10 %.

Done when

The ratio at the current default is recorded with device and date. Then either the backend chooses its own chunk, with pytest -m gpu passing on a CUDA and a HIP build and a scan still forking before the runtime starts, or the issue closes on that number.


Checked against commit 8a9f764. Takes over the roadmap's entry "A device-sized node chunk".

Also

#59's rejected list includes "a device whole-node chunk", which the numbers above from SEP 16 predate. On one radial case the ledger also records one chunk in place of two (48 to 31 kernels a trial) as not moving it, and not adopted. Read those before re-measuring. Tracked in #367.

Activity

  1. added
    performanceSlower or larger than it should be, with no wrong result
    area: backendsAcross backends, and numba_cpu
    area: gpuCUDA and HIP builds: qualification and performance
    on Nov 1, 2026
  2. jtravs commented on Nov 5, 2026

    @jtravs
    ContributorAuthor

    One part of this is measured, and it doesn't pay. #520's temporal collar now works in place on the state's own rows, so its block holds no buffer and costs only launches. So I tried the extreme, every row in one block on a device by default. At 768 x 768 x 600, 8 steps, the median of three runs on one runner, against the node chunk:

    Whole state Node chunk Ratio
    NVIDIA H200 2.661 s 2.671 s 0.996
    AMD Instinct MI325X 2.023 s 2.068 s 0.978

    The plans' device growth is the same to 6 MiB on both. That's well short of the 10 % you asked of a default-memory change, so I dropped it, along with the Transform field it needed. The commit is ae82a2a9 on #520's branch if you want it back. It goes from 119 kernels and 220 transforms a step to 14 and 10, so launches aren't what bounds this step any more.

    That says nothing about the filament row this issue starts from, on Runge-Kutta and Adams, which I didn't re-measure: cartesian_filament_128 waits on #389. So this stays open for that.

  3. jtravs commented on Nov 6, 2026

    @jtravs
    ContributorAuthor

    The whole-state collar is back in #542 for a CUDA or HIP build, with no seam field, as you asked. It passes your rule that an interleaved run on an AMD card has to gain in every round.

    The run was on an AMD Instinct MI300X, ROCm 10.0.0, at c0bd23f2, against the same tree at the node chunk. Each point is field-free, 8 steps with the check off, and the median of a runner's second and third runs. Three rounds of fresh processes alternated between the two builds:

    N x N x 600 Node chunk, s Whole state, s Each round
    384 0.576 0.569 x0.990, x0.988, x0.990
    768 2.172 2.138 x0.984, x0.983, x0.986

    The plans' memory was the same, 5.76 GiB at 768. python -m benchmarks ab --device --length 0.3, 3 rounds, gives kerr_beam_384 x0.952 (0.912–0.999), with the fields identical. On an NVIDIA A40 the same comparison gave kerr_beam_384 x0.989 and kerr_beam_192 x0.971.

    So it stays. That's about 1.5 % of a point, well short of 10 %, but it costs no memory. A CPU keeps the node chunk. The rest of this issue, the chunk being sized at translation for every other source, is untouched, so I've left it open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: backendsAcross backends, and numba_cpuarea: gpuCUDA and HIP builds: qualification and performanceperformanceSlower or larger than it should be, with no wrong resultpriority: lowWorth doing, no hurry

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions