Skip to content

Commit adffd1e

Browse files
Ensure threaded VoA{SArray} regression test actually uses >=2 threads (#570)
The testset added in #564 for `@.. thread=true` on `VectorOfArray{SArray}` only exercises the regression path when `Threads.nthreads() >= 2`. FastBroadcast's Polyester-backed threaded materialize splits work along the last axis via `view(dst, :, r)`; with a single thread that split is a no-op, so the `setindex!` loop that originally blew up on the immutable `SVector` element in issue #570 is never reached. CI currently runs with the default one thread, so the test has been silently passing without actually covering the regression. Guard the testset: when running with >=2 threads, assert in-process as before; otherwise spawn a child `julia --threads=2` process that repeats the broadcast and fails loudly if the result diverges. This guarantees the regression is caught regardless of how the outer test process was launched. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 110f2aa commit adffd1e

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

test/interface_tests.jl

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,16 +291,37 @@ f3!(z, zz)
291291
@test z == VA[fill(4, SVector{2, Float64}), fill(2, SVector{2, Float64})]
292292
@test (@allocated f3!(z, zz)) == 0
293293

294-
# Test threaded FastBroadcast with VectorOfArray of StaticArrays (issue #564)
294+
# Test threaded FastBroadcast with VectorOfArray of StaticArrays (issues #564, #570).
295+
# The regression path in #570 only triggers when Threads.nthreads() >= 2, because
296+
# FastBroadcast's Polyester-backed threaded materialize splits work along the last
297+
# axis via views — with a single thread that split is a no-op and the failing
298+
# setindex! path is never reached. If this test process was launched with only one
299+
# thread (as is currently the default in CI), re-run the testset in a child Julia
300+
# process with `--threads=2` so the multi-thread batch path is actually exercised.
295301
@testset "Threaded @.. with VectorOfArray{SArray}" begin
296-
u_t = VectorOfArray(fill(SVector(1.0, 1.0), 2, 2))
297-
v_t = copy(u_t)
298-
@.. thread = true v_t = v_t + u_t
299-
@test all(x -> x == SVector(2.0, 2.0), v_t.u)
300-
301-
# Test that repeated threaded application accumulates correctly
302-
@.. thread = true v_t = v_t + u_t
303-
@test all(x -> x == SVector(3.0, 3.0), v_t.u)
302+
if Threads.nthreads() >= 2
303+
u_t = VectorOfArray(fill(SVector(1.0, 1.0), 2, 2))
304+
v_t = copy(u_t)
305+
@.. thread = true v_t = v_t + u_t
306+
@test all(x -> x == SVector(2.0, 2.0), v_t.u)
307+
308+
# Test that repeated threaded application accumulates correctly
309+
@.. thread = true v_t = v_t + u_t
310+
@test all(x -> x == SVector(3.0, 3.0), v_t.u)
311+
else
312+
script = """
313+
using RecursiveArrayTools, StaticArrays, FastBroadcast, Polyester
314+
Threads.nthreads() >= 2 || error("subprocess did not start with >= 2 threads")
315+
u_t = VectorOfArray(fill(SVector(1.0, 1.0), 2, 2))
316+
v_t = copy(u_t)
317+
@.. thread = true v_t = v_t + u_t
318+
all(x -> x == SVector(2.0, 2.0), v_t.u) || error("first threaded broadcast wrong: \$(v_t.u)")
319+
@.. thread = true v_t = v_t + u_t
320+
all(x -> x == SVector(3.0, 3.0), v_t.u) || error("second threaded broadcast wrong: \$(v_t.u)")
321+
"""
322+
cmd = `$(Base.julia_cmd()) --threads=2 --startup-file=no --project=$(Base.active_project()) -e $script`
323+
@test success(run(cmd))
324+
end
304325
end
305326

306327
# Test Polyester-based threaded FastBroadcast extension (issue #564)

0 commit comments

Comments
 (0)