Skip to content

perf: use jax.linearize when chunking jacobians in forward-mode - #2286

Open
jpbrodrick89 wants to merge 11 commits into
PlasmaControl:masterfrom
jpbrodrick89:claude/nonlinear-constraints-proximal-67crod
Open

perf: use jax.linearize when chunking jacobians in forward-mode#2286
jpbrodrick89 wants to merge 11 commits into
PlasmaControl:masterfrom
jpbrodrick89:claude/nonlinear-constraints-proximal-67crod

Conversation

@jpbrodrick89

@jpbrodrick89 jpbrodrick89 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

This should provide a runtime and compile time improvement at the possible cost of a very slight peak memory increase. I think if this pushes you over the limit you are probably in the region where you should be switching to iterative rather than direct solvers.

jax.linearize caches the residuals from the primal pass just like jax.vjp does which means sequentially evaluating (chunks of) jvp's it will be a lot faster. For example, if Proximal was fully jittable and went through this route this would have allowed the reuse of the SVD decomposition automatically. As it stands Proximal does not directly benefit but the improvement @YigitElma is making in #2239 should chain nicely with this (it would be interesting to see the benchmarks for these two PR's combined).

@unalmis this should probably be upstreamed in adv-jax-math, lmk if you'd like me to make a PR there.

claude and others added 11 commits August 6, 2026 21:12
…alProjection

ProximalProjection._jvp differentiates the equilibrium constraint w.r.t.
many perturbation directions at a single fixed equilibrium point, chunked
via batched_vectorize for memory. Since dF/dx (restricted to feasible
directions) does not depend on the perturbation direction, only on the
converged equilibrium state, the previous code's use of raw jax.jvp inside
the chunked vmap re-evaluated the nonlinear force-balance residual and
re-factorized its SVD once per chunk instead of once per call, so cost grew
with the number of chunks rather than staying roughly constant.

Use jax.linearize once per xf to get a cheap linear map, and factor its
pseudoinverse once, reusing both across every chunk. Scoped to the
"batched" deriv_mode path (the one that chunks via jac_chunk_size); the
"blocked" fallback is untouched. Verified bitwise-identical jac/jvp output
across chunk sizes against the existing test_proximal_jacobian regression
test, and measured a 2.7-3x speedup on a HELIOTRON equilibrium at chunk
counts that evenly divide the design space.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
…acobians

_jvp_batched builds Jacobians/JVPs by chunking a batch of tangent directions
through batched_vectorize for memory. Since fun's primal does not depend on
the tangent direction, a fresh Derivative.compute_jvp (raw jax.jvp) call
inside every chunk re-evaluates fun's nonlinear primal once per chunk rather
than once per call. This generalizes the fix already applied to
ProximalProjection: add Derivative.linearize (linearize once, get a cheap
reusable jvp function) and use it in _jvp_batched whenever there is more
than one chunk, falling back to the previous behavior otherwise so the
common single-chunk case is untouched. Second/third-order JVPs
(compute_jvp2/compute_jvp3, used by perturbation theory) are intentionally
left as-is for now.

Verified against test_derivatives.py, test_objective_funs.py::test_jvp_scaled,
and test_optimizer.py::test_proximal_jacobian, plus a direct chunk-invariance
check comparing jac_scaled across chunk sizes on a ForceBalance objective.
Note the real-world speedup is problem-dependent: it was substantial for
ProximalProjection's SVD-based tangent construction, but negligible for a
plain ForceBalance Jacobian at the resolution tested here, likely because
that computation is dominated by spectral transform matmuls (linear in the
tangent direction, so their cost is unavoidable either way) rather than by
the nonlinear residual evaluation this fix targets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
…earize

Comment wording: describe the mechanism as jax.linearize's partial
evaluation (compute once, reuse the resulting linear map for many
tangents -- like factorizing a matrix once and reusing it across
right-hand sides), rather than as avoiding a redundant primal
recompute, which reads as something a compiler's DCE should already
handle. Point to jax.linearize's own docs instead of re-explaining it
inline, and trim the comments generally.

_constraint_wrappers.py now calls the new Derivative.linearize instead
of jax.linearize directly, so there is one implementation of "linearize
once" rather than two. It is kept rather than reverted in favor of the
general _jvp_batched fix: the two address different redundancies.
_jvp_batched's fast path only helps the inner jvp_<op> call inside
_get_tangent if that call itself chunks; it cannot reach in and hoist
Fxh/its SVD construction out of ProximalProjection's own outer
chunking loop over v, since that construction lives in
_constraint_wrappers.py, not in _jvp_batched. Recorded that reasoning
as a comment at the call site so the "why not just rely on the general
fix" question is answered in the code, not just in review discussion.

Re-verified: test_optimizer.py::test_proximal_jacobian, test_derivatives.py,
test_objective_funs.py::test_jvp_scaled, and an explicit chunk-invariance
check on jac_scaled/jvp_scaled all still pass after the refactor.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
…ry gap

Found while auditing all batched_vectorize(<jvp-producing-fn>) call sites
for the same pattern already fixed in _jvp_batched/ProximalProjection:

- _Objective._jvp's "fwd" branch (used per sub-objective by
  ObjectiveFunction._jvp_blocked, e.g. when a "blocked"-mode objective's
  jac_scaled is built via jvp_scaled) had the identical unfixed pattern.
  Generalized Derivative.linearize to accept a tuple of argnums (matching
  compute_jvp's interface) since this call site can differentiate w.r.t.
  multiple "things" at once, and applied the same chunk_size-gated fast
  path used in _jvp_batched.

- ProximalProjection.grad() was missed when _jvp was fixed -- it has its
  own separate batched_vectorize(_get_tangent, ...) call and was still
  using the unfixed _get_tangent. Extracted the hoisting logic (build
  Fxh/its pseudoinverse once) into a shared _get_tangent_fun helper used
  by both _jvp and grad, so this can't drift out of sync again.

- Fxh's construction was using plain jax.vmap (desc.backend.vmap, no
  chunking) rather than respecting jac_chunk_size the way the old
  constraint.jvp_<op> call it replaced did. For a large equilibrium this
  drops the memory bound chunking exists for. Switched to
  batched_vectorize with the same chunk_size; f_lin being cheap means
  chunking it now only bounds memory rather than repeating expensive
  work.

Verified: test_optimizer.py::test_proximal_jacobian, test_proximal_grad,
test_derivatives.py, test_objective_funs.py::test_jvp_scaled all pass.
Added explicit chunk-invariance checks for grad() and for a "blocked"-mode
ObjectiveFunction combining fwd/rev sub-objectives, confirming the new
_Objective._jvp path fires (instrumented) and matches the unchunked
reference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
jacfwd_chunked (DESC's local reimplementation of jax.jacfwd, used by
_Objective.jac_scaled/.grad/.hess for any individual objective with
deriv_mode="fwd") had the same raw-jvp-under-chunked-vmap pattern already
fixed elsewhere: pushfwd = partial(_jvp, f_partial, dyn_args) re-evaluates
fun's primal once per scan chunk instead of once overall. This is likely
the most-exercised instance of the four found, since "fwd" is a common
default deriv_mode.

Uses jax.linearize directly (not Derivative.linearize) since desc.batching
is imported by desc.derivatives, so importing back would be circular.
Verified in isolation against jax.jacfwd across chunk sizes for both
single- and multi-argnum cases (the multi-arg case needed a different
calling convention than Derivative.linearize: jax.linearize(fun, *primals)
unpacks primals as separate positional args, but the existing _jvp-based
code here treats dyn_args as one packed pytree argument matching vmap's
in_axes=0 -- wrapping in a single-argument closure keeps that convention).
has_aux=True is left on the old path, matching the precedent set for
higher-order derivatives elsewhere in this series of fixes.

Confirmed via instrumentation the fast path fires exactly once when
chunking occurs and is skipped entirely for a single chunk.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
jacfwd_chunked, add regression tests, and simplify ProximalProjection

Diff-minimization fixes (no behavior change):
- objective_funs.py: drop the local chunk_size variable in two places
  (accessing self._jac_chunk_size is a free attribute read) and collapse
  the branch-then-duplicate-return pattern into build-jvpfun-then-return-once,
  matching the original structure more closely.

ProximalProjection.grad(): was calling compute_scaled_error(xg) then
vjp_scaled_error(g, xg), and vjp_scaled_error's jax.grad internally
re-evaluates the primal to build the backward pass -- so the (possibly
expensive) objective was evaluated twice. Replaced with one jax.vjp call
that returns both the value and a reusable pullback.

jacfwd_chunked (desc/batching.py): restructured so the common no-chunking
case just defers to jax.jacfwd directly instead of reimplementing it,
removing the has_aux special-casing entirely (has_aux now works in the
chunked path too via jax.linearize's own has_aux support, verified against
jax.jacfwd). Also stopped materializing _std_basis just to read its size
for the chunking decision -- the direction count is now computed directly
from the input arguments' sizes.

jacrev_chunked: checked per request -- it already calls jax.vjp exactly
once and only chunks the cheap resulting pullback, so it doesn't have the
redundant-primal bug and wasn't changed. Applying the same "defer when
unchunked" simplification here would need an extra jax.eval_shape pass
just to decide (chunking there depends on output size, which isn't known
until after the forward+vjp), so isn't a clean win the way it was for
jacfwd_chunked.

Regression tests (previously this was only checked with throwaway scripts,
not committed): tests/test_batching.py (new), plus additions to
test_derivatives.py, test_objective_funs.py, and test_optimizer.py. These
assert both numerical chunk-invariance and, via monkeypatching, that
linearize is actually called once rather than once per chunk -- the
property the whole fix series is about, not just "the numbers match".

ProximalProjection simplification: _get_tangent_fun no longer branches on
constraint deriv_mode. It always linearizes the constraint's compute_<op>
as one function now, rather than falling back to differentiating via
constraint.jvp_<op> (dispatching per sub-objective) for "blocked" mode.
This turns out not to lose anything: the only objectives ProximalProjection
accepts as constraints (ForceBalance, CurrentDensity, RadialForceBalance,
HelicalForceBalance) are all dense many-output residuals, so reverse mode
is never actually cheaper for them, and Fxh's SVD downstream was already
computed on one combined matrix regardless of "batched" vs "blocked" --
there was nothing left for "blocked" mode to win by branching. Verified
numerically identical to the old branching behavior for a genuine
multi-sub-objective, mixed fwd/rev "blocked" constraint (RadialForceBalance
+ HelicalForceBalance, which together are equivalent to ForceBalance), both
by direct comparison during development and in the new
test_proximal_always_linearizes_multi_objective_blocked_constraint test.
Old _get_tangent/_proximal_jvp_f_pure (the non-linearized versions) and
_get_tangent_linearized/_proximal_jvp_f_linearized_pure are consolidated
into single _get_tangent/_proximal_jvp_f_pure implementations.

Caught and fixed two test bugs while writing the above: passing
jac_chunk_size to a sub-objective (rather than the outer ObjectiveFunction)
forces "blocked" deriv_mode per ObjectiveFunction's auto-deriv_mode
selection, not "batched" -- so an earlier draft of the batched-mode
regression test was silently exercising the blocked-mode code path instead
of the one it claimed to test. Fixed by asserting the expected deriv_mode
in each test and using the construction that actually produces it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
cross-reference vmap_chunked/batched_vectorize docstrings

- Restored the op= keyword-argument calling convention at both
  _get_tangent_fun call sites (grad, _jvp) -- the original code always
  passed op as a keyword there; an earlier edit had switched to positional.
- Inlined _get_tangent as a nested closure inside _get_tangent_fun (now
  named tangent_fun), and moved the merged method to _get_tangent's
  original file position (after _jvp) rather than _get_tangent_fun's.
  Removes the need to thread f_lin/uf/sfi/vtf through as explicit
  parameters on a separate method -- they're just captured directly now.
- Cross-referenced vmap_chunked and batched_vectorize's docstrings:
  batched_vectorize is built on top of vmap_chunked (calling it once per
  broadcast dimension implied by a gufunc signature) to add
  jax.numpy.vectorize-style broadcasting; vmap_chunked is the lower-level
  primitive, used directly elsewhere in the codebase (e.g. singularities.py)
  for its reduction/chunk_reduction support that batched_vectorize doesn't
  expose. They're not duplicative, just layered -- documented that
  explicitly since the relationship wasn't otherwise obvious from the code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
…nking fix

PR PlasmaControl#2239 (upstream) restructures ProximalProjection's tangent computation
to form the reduced constraint Jacobian densely once, which is a strictly
better fix for the SVD-per-chunk problem than linearizing the per-direction
tangent function. Revert _constraint_wrappers.py to its pre-branch state so
there's no overlap/conflict with that PR, and remove the two tests that
exercised the now-dropped consolidation.

The general Derivative.linearize fix in objective_funs.py/batching.py is
unrelated and still valuable on its own (and is load-bearing for PlasmaControl#2239's own
single jvp_op call once chunked), so it stays.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgWTyAewaigF78JQ6gH6Ry
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Memory benchmark result

|               Test Name                |      %Δ      |    Master (MB)     |      PR (MB)       |    Δ (MB)    |    Time PR (s)     |  Time Master (s)   |
| -------------------------------------- | ------------ | ------------------ | ------------------ | ------------ | ------------------ | ------------------ |
  test_objective_jac_w7x                 |    0.03 %    |     3.985e+03      |     3.986e+03      |     1.00     |       31.07        |       29.63        |
  test_proximal_jac_w7x_with_eq_update   |    3.47 %    |     6.534e+03      |     6.761e+03      |    227.04    |       155.08       |       152.65       |
  test_proximal_freeb_jac                |   -0.35 %    |     1.341e+04      |     1.336e+04      |    -46.28    |       80.32        |       82.21        |
  test_proximal_freeb_jac_blocked        |   -8.77 %    |     7.727e+03      |     7.049e+03      |   -677.75    |       73.27        |       69.00        |
  test_proximal_freeb_jac_batched        |   -7.53 %    |     7.634e+03      |     7.059e+03      |   -574.68    |       72.57        |       69.56        |
  test_proximal_jac_ripple               |   -1.43 %    |     3.597e+03      |     3.546e+03      |    -51.41    |       54.33        |       54.83        |
  test_proximal_jac_ripple_bounce1d      |    1.59 %    |     3.695e+03      |     3.754e+03      |    58.73     |       68.20        |       67.38        |
  test_eq_solve                          |   -6.87 %    |     2.125e+03      |     1.979e+03      |   -145.95    |       54.14        |       53.14        |
  test_objective_quadratic_flux_jac      |   -0.83 %    |     2.537e+03      |     2.516e+03      |    -21.16    |       53.95        |       53.90        |

For the memory plots, go to the summary of Memory Benchmarks workflow and download the artifact.

@YigitElma YigitElma added the run_benchmarks Run timing benchmarks on this PR against current master branch label Aug 10, 2026
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
|             benchmark_name             |         dt(%)          |         dt(s)          |        t_new(s)        |        t_old(s)        | 
| -------------------------------------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
 test_build_transform_fft_lowres         |     +0.51 +/- 4.95     | +4.23e-03 +/- 4.13e-02 |  8.39e-01 +/- 3.1e-02  |  8.35e-01 +/- 2.7e-02  |
 test_equilibrium_init_lowres            |     -1.98 +/- 3.20     | -1.30e-01 +/- 2.10e-01 |  6.42e+00 +/- 1.6e-01  |  6.55e+00 +/- 1.4e-01  |
 test_objective_compile_atf              |     -2.65 +/- 3.52     | -1.55e-01 +/- 2.06e-01 |  5.69e+00 +/- 1.4e-01  |  5.85e+00 +/- 1.5e-01  |
 test_objective_compute_atf              |     -7.21 +/- 9.50     | -2.00e-04 +/- 2.64e-04 |  2.58e-03 +/- 1.3e-04  |  2.78e-03 +/- 2.3e-04  |
 test_objective_jac_atf                  |     -3.32 +/- 4.93     | -6.02e-02 +/- 8.94e-02 |  1.75e+00 +/- 7.0e-02  |  1.81e+00 +/- 5.6e-02  |
 test_perturb_1                          |     -3.62 +/- 2.09     | -4.31e-01 +/- 2.49e-01 |  1.15e+01 +/- 1.8e-01  |  1.19e+01 +/- 1.7e-01  |
 test_proximal_jac_atf                   |     -3.77 +/- 2.15     | -2.06e-01 +/- 1.18e-01 |  5.27e+00 +/- 4.8e-02  |  5.47e+00 +/- 1.1e-01  |
 test_proximal_freeb_compute             |     -3.49 +/- 4.20     | -5.08e-03 +/- 6.11e-03 |  1.41e-01 +/- 4.4e-03  |  1.46e-01 +/- 4.3e-03  |
 test_solve_fixed_iter                   |     -2.06 +/- 2.92     | -5.28e-01 +/- 7.48e-01 |  2.51e+01 +/- 5.2e-01  |  2.56e+01 +/- 5.4e-01  |
 test_LinearConstraintProjection_build   |     -2.60 +/- 3.25     | -1.72e-01 +/- 2.15e-01 |  6.43e+00 +/- 1.0e-01  |  6.60e+00 +/- 1.9e-01  |
 test_objective_compute_ripple           |     +2.65 +/- 6.70     | +5.64e-03 +/- 1.43e-02 |  2.19e-01 +/- 1.3e-02  |  2.13e-01 +/- 6.7e-03  |
 test_objective_grad_ripple              |     -1.43 +/- 3.64     | -1.41e-02 +/- 3.60e-02 |  9.75e-01 +/- 3.0e-02  |  9.89e-01 +/- 2.0e-02  |
 test_objective_quadratic_flux_compute   |     -5.54 +/- 10.47    | -3.24e-03 +/- 6.12e-03 |  5.52e-02 +/- 2.5e-03  |  5.85e-02 +/- 5.6e-03  |
 test_build_transform_fft_midres         |     -0.72 +/- 3.31     | -6.23e-03 +/- 2.86e-02 |  8.59e-01 +/- 1.6e-02  |  8.65e-01 +/- 2.4e-02  |
 test_build_transform_fft_highres        |     +0.54 +/- 3.33     | +6.14e-03 +/- 3.81e-02 |  1.15e+00 +/- 3.1e-02  |  1.14e+00 +/- 2.3e-02  |
 test_equilibrium_init_medres            |     +0.14 +/- 3.80     | +9.79e-03 +/- 2.59e-01 |  6.81e+00 +/- 1.9e-01  |  6.80e+00 +/- 1.7e-01  |
 test_objective_compile_dshape_current   |     -0.30 +/- 3.24     | -1.18e-02 +/- 1.25e-01 |  3.86e+00 +/- 1.2e-01  |  3.87e+00 +/- 4.6e-02  |
 test_objective_compute_dshape_current   |    +10.81 +/- 14.07    | +6.47e-05 +/- 8.42e-05 |  6.63e-04 +/- 7.8e-05  |  5.99e-04 +/- 3.2e-05  |
 test_objective_jac_dshape_current       |    +14.35 +/- 28.13    | +3.29e-03 +/- 6.46e-03 |  2.63e-02 +/- 4.8e-03  |  2.30e-02 +/- 4.3e-03  |
 test_perturb_2                          |     +0.11 +/- 1.39     | +1.69e-02 +/- 2.06e-01 |  1.48e+01 +/- 1.5e-01  |  1.48e+01 +/- 1.5e-01  |
 test_proximal_jac_atf_with_eq_update    |     +0.56 +/- 0.97     | +6.93e-02 +/- 1.21e-01 |  1.26e+01 +/- 8.9e-02  |  1.25e+01 +/- 8.2e-02  |
 test_proximal_freeb_jac                 |     +0.26 +/- 4.12     | +1.23e-02 +/- 1.93e-01 |  4.70e+00 +/- 1.5e-01  |  4.69e+00 +/- 1.2e-01  |
 test_solve_fixed_iter_compiled          |     +0.96 +/- 1.85     | +5.91e-02 +/- 1.14e-01 |  6.21e+00 +/- 9.7e-02  |  6.15e+00 +/- 6.0e-02  |
 test_objective_compute_ripple_bounce1d  |     +1.05 +/- 5.50     | +2.91e-03 +/- 1.52e-02 |  2.80e-01 +/- 1.0e-02  |  2.77e-01 +/- 1.1e-02  |
 test_objective_grad_ripple_bounce1d     |     -0.89 +/- 2.14     | -8.73e-03 +/- 2.09e-02 |  9.71e-01 +/- 1.9e-02  |  9.79e-01 +/- 7.7e-03  |
 test_objective_quadratic_flux_jac       |     +0.30 +/- 0.86     | +2.56e-02 +/- 7.34e-02 |  8.58e+00 +/- 2.0e-02  |  8.55e+00 +/- 7.1e-02  |

Github CI performance can be noisy. When evaluating the benchmarks, developers should take this into account.

@YigitElma

Copy link
Copy Markdown
Collaborator

The failing unit test is related to jax-finufft version. It is similar to the one we faced in #2264. This commit aimed to solve the issue but it didn't and the later commit deleted a unit test which in return moved the failing test to a different Python version that uses a newer jax-finufft (the test passed as if the original commit solved the issue). Anyway, I can fix this in a separate PR, the changes in this PR shouldn't affect Gamma_c at all.

@YigitElma

YigitElma commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Ok, #2287 will resolve the test issue.

I ran this script with different jac_chunk_size values for the objective. The issue in #2239 only happens if ForceBalance constraint is chunked. BoundaryError is one of the expensive objectives, and we usually need to chunk it to fit to the memory, so I guess this is a good representative case for what this PR can achieve.
memory-02_lcp_prox_jac_freeb-gpu

The above plots show the memory usage for chunk sizes of [1, 10, 30, 50, 100, 150, None] and the total batch size is 291. I call the same function 6 times and each time the first shorter peak is constraint evaluation and the second bigger peak is objective evaluation. Note: no chunking could barely fit to my GPU with rematerialization, so the speed comparison is not fair there.

The memory usage for very low chunk sizes increases quite a bit, whereas the evaluation is 2 times faster. They converge to the same speed and the same memory as the chunk size decreases. I checked these on my laptop RTX4080 12GB, having similar thing on cluster A100 would help. I think we need to test this a bit more. We usually accept the slowdown for less memory usage.

@jpbrodrick89

Copy link
Copy Markdown
Contributor Author

This is exactly what I'd expect to see, there is essentially a constant memory overhead equal to keeping the residuals in memory. For a chunk size of one this will be noticeable and its proportional controbution will decrease proportional to chunk size. I think it all depends what chunk size you need to run in production. If its typically O(1) then maybe we should gate linearising to skip when chunk size is small (i think even 1-2 will be reasonable). As i said though if you are running with chunk sizes of 1-2 already my gut feel is youd be better off with iterative Krylov solvers in those cases.

@YigitElma

Copy link
Copy Markdown
Collaborator

Yeah, one weird thing tho (which I realised before but worth mentioning here), sometimes doing the operation in chunks is faster than no chunking or bigger chunks. I guess this depends on the hardware you have and the vectorization capabilities. I mean, sometimes I choose a lower chunk size not for memory purposes but for speed too. I will try to check different types of problems on A100. DESC has many objectives and many options, so it is hard to say whether this is the production run. In the meantime, people are welcome to test it using my repo; it should be quite straightforward when you have a script.

@jpbrodrick89

Copy link
Copy Markdown
Contributor Author

Im surprised that some medium chunk sizes seemed to show a slowdown but I'm guessing this is noise. Also note that for smaller chunk sizes you need more chunks so the speedup might actually be more worth it. I think the interesting thing to check is if you are running at the largest chunk size that fits on an A100 and this PR forces you to shrink that chunk size slightly whether the linearisation speedup compensates for the extra chunks required.

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

Labels

run_benchmarks Run timing benchmarks on this PR against current master branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants