Parellel arrays

I need to have multiple threads write values to a shared array. I’m thinking of having each thread write to a private array, and then have the threads each write their private values into a shared array. In the following example I’ve chosen values that assume 2 threads, and I’m assuming thread 1 has written the values 1 and 2, and thread 2 has written the values 3, 4, 5. A prefix sum is used to let each thread know where to start writing in the shared array (b).

using Base.Threads

function copyVerts!(b, subarray, start, nper, id)
    for i in 1:nper[id]
        b[start[id]+i] = subarray[id][i]
    end
end

# assuming nthreads() is 2
b = Array{Int64,1}(undef,5)
subarray = [similar(b, 0) for i = 1:Threads.nthreads()]
subarray[1] = [1,2]
subarray[2] = [3,4,5]
nper = [2,3]  # thread 1 has 2 values and thread 2 has 3 values
start = cumsum(nper) - nper # exclusive prefix sum
for i = 1:nthreads()
    Threads.@spawn copyVerts!(b, subarray, start, nper, i)
end

This gives:

julia> b
5-element Array{Int64,1}:
 1
 2
 3
 4
 5

Is this a good solution, and how do I wait for all tasks to complete? Feedback would be appreciated.

Just playing around with your idea I came up with the following:

using .Threads

function copyVerts!(b, sub, start)
    for i in 1:length(sub)
        b[start + i - 1] = sub[i]
    end
end

s1 = 1:nthreads()
s2 = s1 .+ 1
c1 = cumsum(s1)
c2 = cumsum(s2)
sa = [c1[i]:c2[i] for i in s1]
b = zeros(Int,maximum(c2))

@sync for i = 1:nthreads()
    Threads.@spawn copyVerts!(b, sa[i], c1[i])
end

then with

julia> nthreads()
8

julia> show(sa)
UnitRange{Int64}[1:2, 3:5, 6:9, 10:14, 15:20, 21:27, 28:35, 36:44]
julia> show(b)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44]

Thanks! It looks basically the same as mine, although I think your copyVerts function is better than mine since you’re taking out reference to the thread index, so you don’t have my indirect indexing (b[start[id]+i]). I used an array of subarrays since I don’t know how long each subarray will be and may have to resize. My example happened to have consecutive integers as the final result, but the final result could have any values.

If the code were to continue past the for loop, how can one wait until all the spawned tasks have completed?

If the code were to continue past the for loop, how can one wait until all the spawned tasks have completed?

@sync.

1 Like

the @sync does this.

1 Like