From 48b7cbacbd283362641cb1704686fbd91ee8a0a3 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 4 Apr 2026 07:40:17 -0400 Subject: [PATCH 1/5] Add Polyester-based threading extension for FastBroadcast VectorOfArray (#564) Replace Base.Threads threading with Polyester @batch in FastBroadcast VectorOfArray extension. When Polyester is loaded, the 3-way extension RecursiveArrayToolsFastBroadcastPolyesterExt provides threaded broadcasting using Polyester.@batch. Without Polyester, threaded broadcasting falls back to serial to avoid issues with mixing Polyester and Base threading. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.6 (1M context) --- Project.toml | 6 ++- ext/RecursiveArrayToolsFastBroadcastExt.jl | 25 ++-------- ...siveArrayToolsFastBroadcastPolyesterExt.jl | 48 +++++++++++++++++++ test/interface_tests.jl | 22 +++++++++ 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl diff --git a/Project.toml b/Project.toml index eadfae50..4bd2dad3 100644 --- a/Project.toml +++ b/Project.toml @@ -26,12 +26,14 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [extensions] RecursiveArrayToolsCUDAExt = "CUDA" RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" +RecursiveArrayToolsFastBroadcastPolyesterExt = ["FastBroadcast", "Polyester"] RecursiveArrayToolsForwardDiffExt = "ForwardDiff" RecursiveArrayToolsKernelAbstractionsExt = "KernelAbstractions" RecursiveArrayToolsMeasurementsExt = "Measurements" @@ -59,6 +61,7 @@ Measurements = "2.11" MonteCarloMeasurements = "1.2" NLsolve = "4.5" Pkg = "1" +Polyester = "0.7.16" PrecompileTools = "1.2.1" Random = "1" RecipesBase = "1.3.4" @@ -86,6 +89,7 @@ Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" @@ -98,4 +102,4 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [targets] -test = ["Aqua", "FastBroadcast", "ForwardDiff", "KernelAbstractions", "Measurements", "NLsolve", "Pkg", "Random", "SafeTestsets", "SparseArrays", "StaticArrays", "Statistics", "StructArrays", "Tables", "Test", "Unitful", "Zygote"] +test = ["Aqua", "FastBroadcast", "ForwardDiff", "KernelAbstractions", "Measurements", "NLsolve", "Pkg", "Polyester", "Random", "SafeTestsets", "SparseArrays", "StaticArrays", "Statistics", "StructArrays", "Tables", "Test", "Unitful", "Zygote"] diff --git a/ext/RecursiveArrayToolsFastBroadcastExt.jl b/ext/RecursiveArrayToolsFastBroadcastExt.jl index 0bc7dc4a..52667bd5 100644 --- a/ext/RecursiveArrayToolsFastBroadcastExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastExt.jl @@ -27,27 +27,10 @@ const AbstractVectorOfSArray = AbstractVectorOfArray{ return dst end -@inline function FastBroadcast.fast_materialize!( - ::Threaded, dst::AbstractVectorOfSArray, - bc::Broadcast.Broadcasted{S} - ) where {S} - if FastBroadcast.use_fast_broadcast(S) - Threads.@threads for i in 1:length(dst.u) - unpacked = RecursiveArrayTools.unpack_voa(bc, i) - dst.u[i] = StaticArraysCore.similar_type(dst.u[i])( - unpacked[j] - for j in eachindex(unpacked) - ) - end - else - Broadcast.materialize!(dst, bc) - end - return dst -end - -# Fallback for non-SArray VectorOfArray: the generic threaded path splits -# along the last axis via views, which does not correctly partition work for -# VectorOfArray. Fall back to serial broadcasting. +# Fallback for VectorOfArray: the generic threaded path splits along the last +# axis via views, which does not correctly partition work for VectorOfArray. +# Fall back to serial broadcasting. The RecursiveArrayToolsFastBroadcastPolyesterExt +# extension provides proper Polyester-based threading when Polyester is loaded. @inline function FastBroadcast.fast_materialize!( ::Threaded, dst::AbstractVectorOfArray, bc::Broadcast.Broadcasted diff --git a/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl new file mode 100644 index 00000000..2e6c2fc2 --- /dev/null +++ b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl @@ -0,0 +1,48 @@ +module RecursiveArrayToolsFastBroadcastPolyesterExt + +using RecursiveArrayTools +using FastBroadcast +using FastBroadcast: Serial, Threaded +using Polyester +using StaticArraysCore + +const AbstractVectorOfSArray = AbstractVectorOfArray{ + T, N, <:AbstractVector{<:StaticArraysCore.SArray}, +} where {T, N} + +@inline function _polyester_fast_materialize!( + dst::AbstractVectorOfSArray, + bc::Broadcast.Broadcasted{S} + ) where {S} + if FastBroadcast.use_fast_broadcast(S) + @batch for i in 1:length(dst.u) + unpacked = RecursiveArrayTools.unpack_voa(bc, i) + dst.u[i] = StaticArraysCore.similar_type(dst.u[i])( + unpacked[j] + for j in eachindex(unpacked) + ) + end + else + Broadcast.materialize!(dst, bc) + end + return dst +end + +@inline function FastBroadcast.fast_materialize!( + ::Threaded, dst::AbstractVectorOfSArray, + bc::Broadcast.Broadcasted{S} + ) where {S} + return _polyester_fast_materialize!(dst, bc) +end + +# Disambiguation: this method is more specific than both the base ext's +# (::Threaded, ::AbstractVectorOfArray, ::Broadcasted) fallback and +# the above (::Threaded, ::AbstractVectorOfSArray, ::Broadcasted{S}). +@inline function FastBroadcast.fast_materialize!( + ::Threaded, dst::AbstractVectorOfSArray, + bc::Broadcast.Broadcasted + ) + return _polyester_fast_materialize!(dst, bc) +end + +end # module diff --git a/test/interface_tests.jl b/test/interface_tests.jl index cc51974a..ff588d40 100644 --- a/test/interface_tests.jl +++ b/test/interface_tests.jl @@ -1,6 +1,7 @@ using RecursiveArrayTools, StaticArrays, Test using RecursiveArrayToolsShorthandConstructors using FastBroadcast +using Polyester using SymbolicIndexingInterface: SymbolCache t = 1:3 @@ -302,6 +303,27 @@ f3!(z, zz) @test all(x -> x == SVector(3.0, 3.0), v_t.u) end +# Test Polyester-based threaded FastBroadcast extension (issue #564) +@testset "Polyester-threaded @.. with VectorOfArray{SArray}" begin + # Verify the Polyester extension is loaded + @test Base.get_extension( + Base.PkgId(RecursiveArrayTools), + :RecursiveArrayToolsFastBroadcastPolyesterExt + ) !== nothing + + # Test basic threaded broadcast with Polyester + u_p = VectorOfArray(fill(SVector(2.0, 3.0), 3, 3)) + v_p = copy(u_p) + @.. thread = true v_p = v_p + u_p + @test all(x -> x == SVector(4.0, 6.0), v_p.u) + + # Test with larger array to exercise Polyester batching + u_large = VectorOfArray(fill(SVector(1.0, 1.0, 1.0), 100)) + v_large = VectorOfArray(fill(SVector(0.0, 0.0, 0.0), 100)) + @.. thread = true v_large = u_large * 2.0 + @test all(x -> x == SVector(2.0, 2.0, 2.0), v_large.u) +end + struct ImmutableVectorOfArray{T, N, A} <: AbstractVectorOfArray{T, N, A} u::A # A <: AbstractArray{<: AbstractArray{T, N - 1}} end From 286ea099695c98fb0639499c159e52a8b1bda673 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sat, 4 Apr 2026 09:48:24 -0400 Subject: [PATCH 2/5] 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 Co-Authored-By: Claude Opus 4.6 (1M context) --- Project.toml | 8 +++++--- ext/RecursiveArrayToolsFastBroadcastExt.jl | 14 ++++++++++---- ...RecursiveArrayToolsFastBroadcastPolyesterExt.jl | 3 +++ src/RecursiveArrayTools.jl | 5 +++++ test/interface_tests.jl | 8 ++++---- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Project.toml b/Project.toml index 4bd2dad3..18b0e5c8 100644 --- a/Project.toml +++ b/Project.toml @@ -7,26 +7,28 @@ authors = ["Chris Rackauckas "] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +RecursiveArrayToolsShorthandConstructors = "39fb7555-b4ad-4efd-8abe-30331df017d3" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5" [weakdeps] CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" -FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" -SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" diff --git a/ext/RecursiveArrayToolsFastBroadcastExt.jl b/ext/RecursiveArrayToolsFastBroadcastExt.jl index 52667bd5..69130653 100644 --- a/ext/RecursiveArrayToolsFastBroadcastExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastExt.jl @@ -27,14 +27,20 @@ const AbstractVectorOfSArray = AbstractVectorOfArray{ return dst end -# Fallback for VectorOfArray: the generic threaded path splits along the last -# axis via views, which does not correctly partition work for VectorOfArray. -# Fall back to serial broadcasting. The RecursiveArrayToolsFastBroadcastPolyesterExt -# extension provides proper Polyester-based threading when Polyester is loaded. +# Fallback for non-SArray VectorOfArray: the generic threaded path splits along +# the last axis via views, which does not correctly partition work for +# VectorOfArray. Fall back to serial broadcasting. +# For SArray VectorOfArray, throw an informative error telling the user to +# load Polyester.jl for threaded broadcasting. @inline function FastBroadcast.fast_materialize!( ::Threaded, dst::AbstractVectorOfArray, bc::Broadcast.Broadcasted ) + if dst isa AbstractVectorOfSArray && !RecursiveArrayTools.POLYESTER_LOADED[] + error("Threaded FastBroadcast on VectorOfArray{SArray} requires Polyester.jl. " * + "Add `using Polyester` to enable threaded broadcasting, or use " * + "`@.. thread=false` for serial broadcasting.") + end return FastBroadcast.fast_materialize!(Serial(), dst, bc) end diff --git a/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl index 2e6c2fc2..9e9837d7 100644 --- a/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl @@ -6,6 +6,9 @@ using FastBroadcast: Serial, Threaded using Polyester using StaticArraysCore +# Signal to the base FastBroadcast extension that Polyester threading is available. +RecursiveArrayTools.POLYESTER_LOADED[] = true + const AbstractVectorOfSArray = AbstractVectorOfArray{ T, N, <:AbstractVector{<:StaticArraysCore.SArray}, } where {T, N} diff --git a/src/RecursiveArrayTools.jl b/src/RecursiveArrayTools.jl index 681e7474..ef135cd1 100644 --- a/src/RecursiveArrayTools.jl +++ b/src/RecursiveArrayTools.jl @@ -195,6 +195,11 @@ module RecursiveArrayTools export ArrayPartition, AP, NamedArrayPartition + # Flag set to `true` by RecursiveArrayToolsFastBroadcastPolyesterExt when + # Polyester is loaded. Checked by the FastBroadcast ext to decide whether + # to throw an informative error on threaded VoA{SArray} operations. + const POLYESTER_LOADED = Ref(false) + include("precompilation.jl") end # module diff --git a/test/interface_tests.jl b/test/interface_tests.jl index ff588d40..91a68a76 100644 --- a/test/interface_tests.jl +++ b/test/interface_tests.jl @@ -311,15 +311,15 @@ end :RecursiveArrayToolsFastBroadcastPolyesterExt ) !== nothing - # Test basic threaded broadcast with Polyester - u_p = VectorOfArray(fill(SVector(2.0, 3.0), 3, 3)) + # Test basic threaded broadcast with Polyester (Vector-of-SVector storage) + u_p = VectorOfArray([SVector(2.0, 3.0) for _ in 1:9]) v_p = copy(u_p) @.. thread = true v_p = v_p + u_p @test all(x -> x == SVector(4.0, 6.0), v_p.u) # Test with larger array to exercise Polyester batching - u_large = VectorOfArray(fill(SVector(1.0, 1.0, 1.0), 100)) - v_large = VectorOfArray(fill(SVector(0.0, 0.0, 0.0), 100)) + u_large = VectorOfArray([SVector(1.0, 1.0, 1.0) for _ in 1:100]) + v_large = VectorOfArray([SVector(0.0, 0.0, 0.0) for _ in 1:100]) @.. thread = true v_large = u_large * 2.0 @test all(x -> x == SVector(2.0, 2.0, 2.0), v_large.u) end From 26866cfb7c618dcccb76c6572c70e53950cf87ad Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 5 Apr 2026 06:36:25 -0400 Subject: [PATCH 3/5] Remove redundant POLYESTER_LOADED flag When Polyester is loaded, RecursiveArrayToolsFastBroadcastPolyesterExt defines more-specific methods for AbstractVectorOfSArray that win dispatch, so the base ext's AbstractVectorOfArray fallback is only reached when Polyester is not loaded. The flag check was redundant. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.6 (1M context) --- ext/RecursiveArrayToolsFastBroadcastExt.jl | 5 ++++- ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl | 3 --- src/RecursiveArrayTools.jl | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/ext/RecursiveArrayToolsFastBroadcastExt.jl b/ext/RecursiveArrayToolsFastBroadcastExt.jl index 69130653..c74b2b3e 100644 --- a/ext/RecursiveArrayToolsFastBroadcastExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastExt.jl @@ -36,7 +36,10 @@ end ::Threaded, dst::AbstractVectorOfArray, bc::Broadcast.Broadcasted ) - if dst isa AbstractVectorOfSArray && !RecursiveArrayTools.POLYESTER_LOADED[] + # When Polyester is loaded, RecursiveArrayToolsFastBroadcastPolyesterExt + # defines more-specific methods for AbstractVectorOfSArray, so reaching + # this method with an SArray VoA means Polyester is not loaded. + if dst isa AbstractVectorOfSArray error("Threaded FastBroadcast on VectorOfArray{SArray} requires Polyester.jl. " * "Add `using Polyester` to enable threaded broadcasting, or use " * "`@.. thread=false` for serial broadcasting.") diff --git a/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl index 9e9837d7..2e6c2fc2 100644 --- a/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastPolyesterExt.jl @@ -6,9 +6,6 @@ using FastBroadcast: Serial, Threaded using Polyester using StaticArraysCore -# Signal to the base FastBroadcast extension that Polyester threading is available. -RecursiveArrayTools.POLYESTER_LOADED[] = true - const AbstractVectorOfSArray = AbstractVectorOfArray{ T, N, <:AbstractVector{<:StaticArraysCore.SArray}, } where {T, N} diff --git a/src/RecursiveArrayTools.jl b/src/RecursiveArrayTools.jl index ef135cd1..681e7474 100644 --- a/src/RecursiveArrayTools.jl +++ b/src/RecursiveArrayTools.jl @@ -195,11 +195,6 @@ module RecursiveArrayTools export ArrayPartition, AP, NamedArrayPartition - # Flag set to `true` by RecursiveArrayToolsFastBroadcastPolyesterExt when - # Polyester is loaded. Checked by the FastBroadcast ext to decide whether - # to throw an informative error on threaded VoA{SArray} operations. - const POLYESTER_LOADED = Ref(false) - include("precompilation.jl") end # module From 42341547c6fdf473bd8097fa846cbfe4bd80939e Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 5 Apr 2026 07:25:55 -0400 Subject: [PATCH 4/5] Fix Project.toml: move weakdeps back out of [deps] Commit 286ea09 accidentally moved FastBroadcast, Polyester, SparseArrays, StaticArrays, and RecursiveArrayToolsShorthandConstructors into [deps] (they were added there by stray Pkg.add/Pkg.develop calls during development). Restore FastBroadcast/Polyester/SparseArrays to [weakdeps] and drop StaticArrays/ShorthandConstructors (they are test-only). This fixes the Aqua stale_deps and deps_compat failures on Julia 1.10 CI, which were caused by the polluted [deps] triggering a circular precompile with the ShorthandConstructors subpackage dev'd in runtests.jl. Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.6 (1M context) --- Project.toml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 18b0e5c8..0488c683 100644 --- a/Project.toml +++ b/Project.toml @@ -7,25 +7,23 @@ authors = ["Chris Rackauckas "] Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" -FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" -RecursiveArrayToolsShorthandConstructors = "39fb7555-b4ad-4efd-8abe-30331df017d3" -SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5" [weakdeps] CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" +Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" From 4335a0d334df42b9b2eff1dcd55f4f086bb60108 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Sun, 5 Apr 2026 08:06:40 -0400 Subject: [PATCH 5/5] Apply Runic formatting Co-Authored-By: Chris Rackauckas Co-Authored-By: Claude Opus 4.6 (1M context) --- ext/RecursiveArrayToolsFastBroadcastExt.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/RecursiveArrayToolsFastBroadcastExt.jl b/ext/RecursiveArrayToolsFastBroadcastExt.jl index c74b2b3e..f8d3ce3d 100644 --- a/ext/RecursiveArrayToolsFastBroadcastExt.jl +++ b/ext/RecursiveArrayToolsFastBroadcastExt.jl @@ -40,9 +40,11 @@ end # defines more-specific methods for AbstractVectorOfSArray, so reaching # this method with an SArray VoA means Polyester is not loaded. if dst isa AbstractVectorOfSArray - error("Threaded FastBroadcast on VectorOfArray{SArray} requires Polyester.jl. " * - "Add `using Polyester` to enable threaded broadcasting, or use " * - "`@.. thread=false` for serial broadcasting.") + error( + "Threaded FastBroadcast on VectorOfArray{SArray} requires Polyester.jl. " * + "Add `using Polyester` to enable threaded broadcasting, or use " * + "`@.. thread=false` for serial broadcasting." + ) end return FastBroadcast.fast_materialize!(Serial(), dst, bc) end