diff --git a/src/mapreduce.jl b/src/mapreduce.jl index 3d657d7..51c6607 100644 --- a/src/mapreduce.jl +++ b/src/mapreduce.jl @@ -209,22 +209,24 @@ function _mapreduce_block!( T = eltype(arrays[1]) spacing = isbitstype(T) ? max(1, div(64, sizeof(T))) : 1 # to avoid false sharing threadedout = similar(arrays[1], spacing * get_num_threads()) - a = arrays[1][ParentIndex(1)] + iout = ParentIndex(offsets[1] + 1) + a = arrays[1][iout] if initop !== nothing a = initop(a) end _init_reduction!(threadedout, f, op, a) newarrays = (threadedout, Base.tail(arrays)...) + newoffsets = (offset(threadedout), Base.tail(offsets)...) _mapreduce_threaded!( - f, op, nothing, dims, blocks, strides, offsets, costs, + f, op, nothing, dims, blocks, strides, newoffsets, costs, newarrays, get_num_threads(), spacing, 1 ) for i in 1:get_num_threads() a = op(a, threadedout[(i - 1) * spacing + 1]) end - arrays[1][ParentIndex(1)] = a + arrays[1][iout] = a else costs = costs .* .!(iszero.(strides[1])) # make cost of dimensions with zero stride in output array (reduction dimensions), diff --git a/test/othertests.jl b/test/othertests.jl index 11dc94c..44eaee9 100644 --- a/test/othertests.jl +++ b/test/othertests.jl @@ -161,6 +161,24 @@ end R3 = rand(T, (5, 5, 5)) @test prod(exp, StridedView(R3)) ≈ exp(sum(StridedView(R3))) + + # Large enough to exercise threaded reduction, with offsets in both views. + n = 2 * Strided.MINTHREADLENGTH + input = sview(StridedView(fill(T(2), n + 20)), 11:(n + 10)) + for initop in (nothing, zero, x -> 3x) + storage = StridedView(fill(T(99), 12)) + output = sview(storage, 5:5) + fill!(output, T(7)) + if initop === nothing + Base.mapreducedim!(identity, +, output, input) + else + Strided._mapreducedim!(identity, +, initop, (n,), (output, input)) + end + initial = initop === nothing ? T(7) : initop(T(7)) + expected = fill(T(99), 12) + expected[5] = initial + T(2) * n + @test Array(storage) == expected + end end end