Skip to content

Launch kernels over a list of indices - #772

Open
giordano wants to merge 4 commits into
mainfrom
mg/ndrange-index-map
Open

giordano wants to merge 4 commits into
mainfrom
mg/ndrange-index-map

Conversation

@giordano

Copy link
Copy Markdown
Collaborator

Redo of #765, in this repo. Ref: #757. CC @simone-silvestri.

@giordano
giordano added this pull request to stack #773 September 11, 2026 22:35
@giordano
giordano force-pushed the mg/ndrange-index-map branch from c0b180e to c4daa40 Compare September 11, 2026 22:35
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Show table
main 37c4780... main / 37c4780...
launch/3D static workgroup, dynamic ndrange 22.3 ± 13 μs 20.8 ± 9.2 μs 1.07 ± 0.8
launch/3D static workgroup, static ndrange 21.3 ± 11 μs 20.8 ± 10 μs 1.02 ± 0.72
launch/dynamic workgroup, dynamic ndrange 20.2 ± 7.1 μs 21.4 ± 8.4 μs 0.947 ± 0.5
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 21 ± 9.8 μs 21.3 ± 12 μs 0.986 ± 0.71
launch/static workgroup, dynamic ndrange 20.7 ± 10 μs 21 ± 13 μs 0.987 ± 0.77
launch/static workgroup, static ndrange 21.4 ± 11 μs 21.1 ± 12 μs 1.01 ± 0.78
partition/dynamic workgroup, dynamic ndrange 0.0481 ± 0.01 μs 0.0503 ± 0.011 μs 0.956 ± 0.29
partition/static workgroup, dynamic ndrange 0.0556 ± 0.0077 μs 0.0536 ± 0.011 μs 1.04 ± 0.26
partition/static workgroup, static ndrange 1.16 ± 0.005 ns 1.27 ± 0.0092 ns 0.913 ± 0.0077
saxpy/default/Float16/1024 25.7 ± 20 μs 26.9 ± 23 μs 0.953 ± 1.1
saxpy/default/Float16/1048576 0.339 ± 0.025 ms 0.34 ± 0.022 ms 0.995 ± 0.098
saxpy/default/Float16/16384 0.0428 ± 0.023 ms 0.0407 ± 0.021 ms 1.05 ± 0.78
saxpy/default/Float16/2048 30.9 ± 22 μs 31 ± 21 μs 0.996 ± 0.97
saxpy/default/Float16/256 22.6 ± 10 μs 22.7 ± 11 μs 0.996 ± 0.65
saxpy/default/Float16/262144 0.117 ± 0.022 ms 0.115 ± 0.022 ms 1.02 ± 0.27
saxpy/default/Float16/32768 0.0528 ± 0.025 ms 0.0547 ± 0.026 ms 0.965 ± 0.65
saxpy/default/Float16/4096 0.0368 ± 0.023 ms 0.0464 ± 0.022 ms 0.792 ± 0.63
saxpy/default/Float16/512 22.8 ± 12 μs 22.3 ± 11 μs 1.02 ± 0.72
saxpy/default/Float16/64 22.4 ± 10 μs 22.4 ± 12 μs 0.999 ± 0.72
saxpy/default/Float16/65536 0.0535 ± 0.022 ms 0.0541 ± 0.022 ms 0.988 ± 0.56
saxpy/default/Float32/1024 27.3 ± 25 μs 26.1 ± 24 μs 1.05 ± 1.4
saxpy/default/Float32/1048576 0.388 ± 0.055 ms 0.391 ± 0.053 ms 0.992 ± 0.19
saxpy/default/Float32/16384 0.048 ± 0.025 ms 0.0493 ± 0.025 ms 0.975 ± 0.71
saxpy/default/Float32/2048 0.0458 ± 0.022 ms 0.0405 ± 0.023 ms 1.13 ± 0.85
saxpy/default/Float32/256 21.9 ± 10 μs 22.8 ± 11 μs 0.959 ± 0.65
saxpy/default/Float32/262144 0.112 ± 0.019 ms 0.11 ± 0.019 ms 1.02 ± 0.24
saxpy/default/Float32/32768 0.0459 ± 0.024 ms 0.0528 ± 0.026 ms 0.869 ± 0.62
saxpy/default/Float32/4096 0.0483 ± 0.022 ms 0.0449 ± 0.024 ms 1.08 ± 0.74
saxpy/default/Float32/512 24.7 ± 24 μs 24.9 ± 25 μs 0.992 ± 1.4
saxpy/default/Float32/64 22.4 ± 10 μs 22.8 ± 15 μs 0.983 ± 0.8
saxpy/default/Float32/65536 0.0581 ± 0.025 ms 0.0589 ± 0.025 ms 0.987 ± 0.59
saxpy/default/Float64/1024 0.0354 ± 0.026 ms 0.0336 ± 0.026 ms 1.05 ± 1.1
saxpy/default/Float64/1048576 0.68 ± 0.1 ms 0.695 ± 0.096 ms 0.98 ± 0.2
saxpy/default/Float64/16384 0.0453 ± 0.024 ms 0.0479 ± 0.025 ms 0.948 ± 0.71
saxpy/default/Float64/2048 0.0415 ± 0.025 ms 0.0397 ± 0.024 ms 1.05 ± 0.89
saxpy/default/Float64/256 23.7 ± 19 μs 22.7 ± 13 μs 1.05 ± 1
saxpy/default/Float64/262144 0.192 ± 0.032 ms 0.184 ± 0.036 ms 1.04 ± 0.27
saxpy/default/Float64/32768 0.0563 ± 0.028 ms 0.0532 ± 0.026 ms 1.06 ± 0.74
saxpy/default/Float64/4096 0.0494 ± 0.024 ms 0.0399 ± 0.026 ms 1.24 ± 1
saxpy/default/Float64/512 23.2 ± 16 μs 21.9 ± 11 μs 1.06 ± 0.91
saxpy/default/Float64/64 22.3 ± 8.6 μs 22.6 ± 13 μs 0.987 ± 0.67
saxpy/default/Float64/65536 0.0702 ± 0.026 ms 0.0656 ± 0.023 ms 1.07 ± 0.55
saxpy/static workgroup=(1024,)/Float16/1024 25.7 ± 21 μs 24.7 ± 20 μs 1.04 ± 1.2
saxpy/static workgroup=(1024,)/Float16/1048576 0.329 ± 0.027 ms 0.331 ± 0.026 ms 0.993 ± 0.11
saxpy/static workgroup=(1024,)/Float16/16384 0.0398 ± 0.021 ms 0.0397 ± 0.02 ms 1 ± 0.73
saxpy/static workgroup=(1024,)/Float16/2048 29.7 ± 21 μs 29 ± 20 μs 1.02 ± 1
saxpy/static workgroup=(1024,)/Float16/256 25.4 ± 20 μs 24.9 ± 20 μs 1.02 ± 1.1
saxpy/static workgroup=(1024,)/Float16/262144 0.112 ± 0.02 ms 0.112 ± 0.021 ms 0.998 ± 0.26
saxpy/static workgroup=(1024,)/Float16/32768 0.051 ± 0.024 ms 0.0463 ± 0.022 ms 1.1 ± 0.74
saxpy/static workgroup=(1024,)/Float16/4096 0.044 ± 0.019 ms 0.038 ± 0.021 ms 1.16 ± 0.82
saxpy/static workgroup=(1024,)/Float16/512 25.3 ± 21 μs 24.8 ± 20 μs 1.02 ± 1.2
saxpy/static workgroup=(1024,)/Float16/64 25.1 ± 20 μs 24.9 ± 18 μs 1.01 ± 1.1
saxpy/static workgroup=(1024,)/Float16/65536 0.0517 ± 0.021 ms 0.0506 ± 0.021 ms 1.02 ± 0.59
saxpy/static workgroup=(1024,)/Float32/1024 25.8 ± 24 μs 26.4 ± 24 μs 0.976 ± 1.3
saxpy/static workgroup=(1024,)/Float32/1048576 0.374 ± 0.057 ms 0.374 ± 0.059 ms 0.998 ± 0.22
saxpy/static workgroup=(1024,)/Float32/16384 0.0457 ± 0.024 ms 0.0463 ± 0.025 ms 0.987 ± 0.73
saxpy/static workgroup=(1024,)/Float32/2048 0.0423 ± 0.021 ms 0.0431 ± 0.021 ms 0.982 ± 0.7
saxpy/static workgroup=(1024,)/Float32/256 25.1 ± 20 μs 24.6 ± 20 μs 1.02 ± 1.2
saxpy/static workgroup=(1024,)/Float32/262144 0.107 ± 0.019 ms 0.106 ± 0.019 ms 1.01 ± 0.25
saxpy/static workgroup=(1024,)/Float32/32768 0.0494 ± 0.025 ms 0.0493 ± 0.024 ms 1 ± 0.7
saxpy/static workgroup=(1024,)/Float32/4096 0.046 ± 0.02 ms 0.0425 ± 0.022 ms 1.08 ± 0.73
saxpy/static workgroup=(1024,)/Float32/512 25.3 ± 22 μs 24.4 ± 22 μs 1.03 ± 1.3
saxpy/static workgroup=(1024,)/Float32/64 23.9 ± 16 μs 23.7 ± 17 μs 1.01 ± 1
saxpy/static workgroup=(1024,)/Float32/65536 0.0527 ± 0.023 ms 0.0539 ± 0.023 ms 0.978 ± 0.6
saxpy/static workgroup=(1024,)/Float64/1024 30.4 ± 25 μs 31 ± 25 μs 0.978 ± 1.1
saxpy/static workgroup=(1024,)/Float64/1048576 0.694 ± 0.11 ms 0.714 ± 0.092 ms 0.971 ± 0.2
saxpy/static workgroup=(1024,)/Float64/16384 0.0462 ± 0.024 ms 0.0467 ± 0.024 ms 0.989 ± 0.72
saxpy/static workgroup=(1024,)/Float64/2048 0.0333 ± 0.023 ms 0.0395 ± 0.023 ms 0.845 ± 0.77
saxpy/static workgroup=(1024,)/Float64/256 27.8 ± 21 μs 27.9 ± 21 μs 0.995 ± 1.1
saxpy/static workgroup=(1024,)/Float64/262144 0.188 ± 0.032 ms 0.184 ± 0.031 ms 1.02 ± 0.25
saxpy/static workgroup=(1024,)/Float64/32768 0.0522 ± 0.023 ms 0.0515 ± 0.024 ms 1.01 ± 0.65
saxpy/static workgroup=(1024,)/Float64/4096 0.0447 ± 0.02 ms 0.0465 ± 0.02 ms 0.961 ± 0.59
saxpy/static workgroup=(1024,)/Float64/512 25.8 ± 21 μs 26.8 ± 22 μs 0.963 ± 1.1
saxpy/static workgroup=(1024,)/Float64/64 25.2 ± 18 μs 25.3 ± 21 μs 0.993 ± 1.1
saxpy/static workgroup=(1024,)/Float64/65536 0.0652 ± 0.023 ms 0.0642 ± 0.023 ms 1.02 ± 0.51
time_to_load 0.699 ± 0.0054 s 0.706 ± 0.0033 s 0.99 ± 0.009
main 37c4780... main / 37c4780...
launch/3D static workgroup, dynamic ndrange 7 allocs: 0.297 kB 7 allocs: 0.297 kB 1
launch/3D static workgroup, static ndrange 8 allocs: 0.328 kB 8 allocs: 0.328 kB 1
launch/dynamic workgroup, dynamic ndrange 17 allocs: 0.469 kB 17 allocs: 0.469 kB 1
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
launch/static workgroup, dynamic ndrange 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
launch/static workgroup, static ndrange 4 allocs: 0.203 kB 4 allocs: 0.203 kB 1
partition/dynamic workgroup, dynamic ndrange 2 allocs: 0.0625 kB 2 allocs: 0.0625 kB 1
partition/static workgroup, dynamic ndrange 2 allocs: 32 B 2 allocs: 32 B 1
partition/static workgroup, static ndrange 0 allocs: 0 B 0 allocs: 0 B
saxpy/default/Float16/1024 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/1048576 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/16384 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/2048 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/256 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float16/262144 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/32768 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/4096 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/512 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float16/64 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float16/65536 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/1024 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/1048576 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/16384 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/2048 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/256 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float32/262144 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/32768 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/4096 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/512 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float32/64 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float32/65536 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/1024 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/1048576 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/16384 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/2048 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/256 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float64/262144 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/32768 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/4096 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/512 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/default/Float64/64 18 allocs: 0.484 kB 18 allocs: 0.484 kB 1
saxpy/default/Float64/65536 26 allocs: 0.609 kB 26 allocs: 0.609 kB 1
saxpy/static workgroup=(1024,)/Float16/1024 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/1048576 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/16384 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/2048 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/256 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float16/262144 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/32768 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/4096 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/512 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float16/64 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float16/65536 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/1024 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/1048576 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/16384 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/2048 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/256 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float32/262144 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/32768 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/4096 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/512 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float32/64 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float32/65536 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/1024 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/1048576 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/16384 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/2048 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/256 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float64/262144 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/32768 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/4096 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/512 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
saxpy/static workgroup=(1024,)/Float64/64 3 allocs: 0.172 kB 3 allocs: 0.172 kB 1
saxpy/static workgroup=(1024,)/Float64/65536 6 allocs: 0.219 kB 6 allocs: 0.219 kB 1
time_to_load 0.205 k allocs: 12 kB 0.201 k allocs: 11.8 kB 1.02

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

@giordano
giordano force-pushed the mg/ndrange-index-map branch from c4daa40 to aa7d1ca Compare September 12, 2026 17:30
@christiangnrd

Copy link
Copy Markdown
Member

Reposting @vchuravy's comment here:

  • ndrange may be a device vector of CartesianIndex/NTuple indices, running one work item per
    listed index (kernel(A, ndrange=active_cells)).

I think that's a step too far.

The user could have simply written:

ndrange=length(active_cells) and then done. idx = active_cells(@index Global)

Originally posted by @vchuravy in #765 (comment)

@vchuravy
vchuravy force-pushed the mg/ndrange-index-map branch from aa7d1ca to 13f4f01 Compare September 13, 2026 12:21
Base automatically changed from mg/ndrange-offsets to main September 13, 2026 16:03
`ndrange` may now be a device vector of `CartesianIndex{N}` or
`NTuple{N, <:Integer}` elements. Each work item handles one listed index:
`@index(Global, Cartesian)` and `@index(Global, NTuple)` return it,
`@index(Global, Linear)` its position in the vector, `@ndrange()` the
vector's length. The kernel must have a dynamic `ndrange` and a 1-D
workgroup size, static or given at launch; the partial last workgroup is
bounds-checked against the vector's length.

This is how Oceananigans iterates over the active cells of an immersed
boundary grid. It currently wraps the kernel function, pirates
`Base.getproperty` on `Kernel`, `Adapt.adapt_structure` on `NDRange`
and `CompilerMetadata`, `partition`, `expand`, and adds one
`@device_override __validindex` per GPU backend, which the compiled CPU
backend's own `::Any` override shadows.

Implementation:
- `IndexMap{N}` wraps the vector and yields `CartesianIndex{N}` on
  indexing; it is the `mapping` of a 1-D `NDRange` (`MappedNDRange`).
  `expand` and `linear_index` on a `MappedNDRange` look the index up.
- `partition` dispatches vectors to `mapped_partition`, which validates
  the kernel and workgroup size and partitions `(length(map),)`; the
  dynamic-check flag is computed as for any other ndrange.
- Index validity moves into the generic `__validindex(ctx, groupidx,
  idx)`, which dispatches on the iteration space (`I in ndrange` for
  regular spaces, position `<= length(map)` for index maps). The 1-arg
  `__validindex(ctx)` is now a plain method built on
  `KernelInterface.get_group_id`/`get_local_id`, so the POCL override is
  removed; `__index_Global_Linear` goes through `__global_linear` in the
  same way. Backends that still override `__validindex(ctx)` keep
  working for regular ndranges and should forward to the 3-arg method
  to support index maps.
- `Adapt.adapt_structure` for `NDRange`, `IndexMap` and
  `CompilerMetadata` moves the vector to the device with the kernel
  arguments; `CompilerMetadata` treats a vector `ndrange` as
  `CartesianIndices((length(v),))`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHciC8x39gm97sABrSvBkt
@vchuravy
vchuravy force-pushed the mg/ndrange-index-map branch from 13f4f01 to 39488ea Compare September 13, 2026 16:03
@giordano giordano mentioned this pull request Sep 13, 2026
giordano and others added 3 commits September 13, 2026 15:34
Backends check the validity of a work item as `I in __ndrange(ctx)`, with
`I` from `expand` or `__index_Global_Cartesian`. For a launch over an
index map that compared an N-D index against a 1-D range, so every lane
was inactive on OpenCL.jl. `expand` on a `MappedNDRange` now returns an
`invalid_index` (`typemin(Int)` along every axis) for work items past
the end of the map, and the `ndrange` of such a launch is a
`MappedIndices`, which rejects only that index.

Also fix the `Const` test: the CPU backend compiles with POCL, so the
host `code_llvm` it used produced a kernel that only threw. Launch the
kernel and check the result on every backend instead, keeping the IR
checks for CUDA and ROCm.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSb4tbVQi1dbKWvaP6R6EE
The docstrings of `MappedNDRange`, `MappedIndices` and `invalid_index`
link to it, which made the docs build fail.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CSb4tbVQi1dbKWvaP6R6EE
@giordano

Copy link
Copy Markdown
Collaborator Author

Based on quick testing, we may not need this in Oceananigans after all, and #771 should be sufficient (it's hard to do full testing at the moment though, because of #734 (comment)). I'm leaving this open in case it's still useful for #779.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants