Skip to content

Commit 286ea09

Browse files
Add informative error when threading VoA{SArray} without Polyester
When Polyester is not loaded and a user requests threaded FastBroadcast on VectorOfArray{SArray}, throw an error explaining they need to load Polyester.jl. Also fix tests to use Vector-of-SVector construction (not Matrix-of-SVector) to properly exercise the SArray-specific path. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 48b7cba commit 286ea09

5 files changed

Lines changed: 27 additions & 11 deletions

Project.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,28 @@ authors = ["Chris Rackauckas <accounts@chrisrackauckas.com>"]
77
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
88
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
99
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
10+
FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898"
1011
GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527"
1112
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
13+
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
1214
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
1315
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
16+
RecursiveArrayToolsShorthandConstructors = "39fb7555-b4ad-4efd-8abe-30331df017d3"
17+
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
18+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1419
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
1520
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
1621

1722
[weakdeps]
1823
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
19-
FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898"
2024
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
2125
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
2226
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
2327
MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca"
2428
ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267"
25-
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
2629
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
2730
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
2831
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
29-
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
3032
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
3133
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
3234

ext/RecursiveArrayToolsFastBroadcastExt.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@ const AbstractVectorOfSArray = AbstractVectorOfArray{
2727
return dst
2828
end
2929

30-
# Fallback for VectorOfArray: the generic threaded path splits along the last
31-
# axis via views, which does not correctly partition work for VectorOfArray.
32-
# Fall back to serial broadcasting. The RecursiveArrayToolsFastBroadcastPolyesterExt
33-
# extension provides proper Polyester-based threading when Polyester is loaded.
30+
# Fallback for non-SArray VectorOfArray: the generic threaded path splits along
31+
# the last axis via views, which does not correctly partition work for
32+
# VectorOfArray. Fall back to serial broadcasting.
33+
# For SArray VectorOfArray, throw an informative error telling the user to
34+
# load Polyester.jl for threaded broadcasting.
3435
@inline function FastBroadcast.fast_materialize!(
3536
::Threaded, dst::AbstractVectorOfArray,
3637
bc::Broadcast.Broadcasted
3738
)
39+
if dst isa AbstractVectorOfSArray && !RecursiveArrayTools.POLYESTER_LOADED[]
40+
error("Threaded FastBroadcast on VectorOfArray{SArray} requires Polyester.jl. " *
41+
"Add `using Polyester` to enable threaded broadcasting, or use " *
42+
"`@.. thread=false` for serial broadcasting.")
43+
end
3844
return FastBroadcast.fast_materialize!(Serial(), dst, bc)
3945
end
4046

ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ using FastBroadcast: Serial, Threaded
66
using Polyester
77
using StaticArraysCore
88

9+
# Signal to the base FastBroadcast extension that Polyester threading is available.
10+
RecursiveArrayTools.POLYESTER_LOADED[] = true
11+
912
const AbstractVectorOfSArray = AbstractVectorOfArray{
1013
T, N, <:AbstractVector{<:StaticArraysCore.SArray},
1114
} where {T, N}

src/RecursiveArrayTools.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ module RecursiveArrayTools
195195

196196
export ArrayPartition, AP, NamedArrayPartition
197197

198+
# Flag set to `true` by RecursiveArrayToolsFastBroadcastPolyesterExt when
199+
# Polyester is loaded. Checked by the FastBroadcast ext to decide whether
200+
# to throw an informative error on threaded VoA{SArray} operations.
201+
const POLYESTER_LOADED = Ref(false)
202+
198203
include("precompilation.jl")
199204

200205
end # module

test/interface_tests.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,15 +311,15 @@ end
311311
:RecursiveArrayToolsFastBroadcastPolyesterExt
312312
) !== nothing
313313

314-
# Test basic threaded broadcast with Polyester
315-
u_p = VectorOfArray(fill(SVector(2.0, 3.0), 3, 3))
314+
# Test basic threaded broadcast with Polyester (Vector-of-SVector storage)
315+
u_p = VectorOfArray([SVector(2.0, 3.0) for _ in 1:9])
316316
v_p = copy(u_p)
317317
@.. thread = true v_p = v_p + u_p
318318
@test all(x -> x == SVector(4.0, 6.0), v_p.u)
319319

320320
# Test with larger array to exercise Polyester batching
321-
u_large = VectorOfArray(fill(SVector(1.0, 1.0, 1.0), 100))
322-
v_large = VectorOfArray(fill(SVector(0.0, 0.0, 0.0), 100))
321+
u_large = VectorOfArray([SVector(1.0, 1.0, 1.0) for _ in 1:100])
322+
v_large = VectorOfArray([SVector(0.0, 0.0, 0.0) for _ in 1:100])
323323
@.. thread = true v_large = u_large * 2.0
324324
@test all(x -> x == SVector(2.0, 2.0, 2.0), v_large.u)
325325
end

0 commit comments

Comments
 (0)