Skip to content

fix(cpu): apply! is unsafe when input/output are SubArray views #64

Description

@kylebeggs

Symptom

A downstream package cannot use MFO's (or KernelAbstractions') CPU kernel path when the state it passes is a SubArray view, because the KA CPU() backend races on views. It works on GPU backends and it works on plain Arrays; it corrupts results on CPU + views.

Why that shape comes up

It is not exotic. A folded steady solve marches a stacked state and hands each species' slice to the diffusion operator as a view — that is the natural, allocation-free way to apply a per-species operator to a multi-species state without copying. Any solver that stacks fields and slices them hits this.

What downstream had to do

The workaround in the microvascular model is an entire file that exists for no other reason:

# CPU uses a plain scalar loop over laplacian_7pt_noflux (view- and thread-safe);
# the GPU path delegates to the KA stencil (identical numerics). The split exists
# because KA's CPU() backend races on the SubArray views the folded steady solve passes.
_tissue_laplacian!(out, u, grid) = _tissue_laplacian!(out, u, grid, get_backend(u))
_tissue_laplacian!(out, u, grid, ::CPU) = # hand-rolled scalar loop
_tissue_laplacian!(out, u, grid, backend) = # delegate to the KA kernel

Two code paths, two sets of numerics to keep in agreement, forever — to work around a backend property. This is the single clearest case of "downstream reimplemented something because MFO's version didn't fit", and it's the one I'd most like to delete.

Ask

Either make the CPU apply! path view-safe, or — if that is genuinely KA's problem rather than MFO's — document the constraint loudly and offer a sanctioned view-safe CPU fallback in MFO so every downstream doesn't hand-roll its own.

Related to #51 (CPU apply! is single-threaded): both are about the CPU path being the odd one out, and a rework that fixes threading is the natural place to fix view-safety too. laplacian_7pt_noflux is already documented as the escape hatch for fused custom kernels over flat state, so the raw ingredient is there — what's missing is a supported loop around it.


🤖 Written by Claude. If this is wrong, blame the robot, not the human whose name is on the repo.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions