Appears to be an issue for me on both Julia 1.1 and 1.3.alpha-0. Not tried other builds.
I am using a array of falses AList=(falses(n)) and A=view(AList) inside the the threaded loop.
using Dislocations
include("...\test\TestThreads.jl")
This loops some threaded code, around 20 loops inside this test for me (sometimes more sometimes less it) it fails. If I turn threads off (line 75 of Triangular.jl) it gives me the expected result. If not (threads are on) this fails, I reset the viewed array on line 454-458 so it shouldnt matter…?. If inside the threaded loop I turn on lines 83-85 (this just inits the falses array inside the loop) then this works fine (kind of expected).
I have not looked at your example in detail. However, falses(sz) creates a BitArray, not a bool array.
Your CPU is capable of byte (i.e. Bool)-sized reads and writes, and access to bool arrays is therefore threadsafe (as long as you avoid actual data races, no new ones will be introduced; still, your CPU will slow down to a crawl for parallel not-read-only access that shares a cache line).
No sensible CPU is capable of bit addressing. BitArray store 64 bit in one integer, and bits that share a single UInt64 in storage alias. This means that @threads for i in 1:n A[i] = rand(Bool) end will have race conditions if A is a BitArray (unless there are some divisibility conditions between nthreads(), length(A) and 64).
BitArray is not thread-safe unless you either access read-only, or know very precisely what you are doing.
Yes, it’s a bit array not a bool array, I was being naïve. I also hadn’t realised this was complex for BitArrays. Are there plans to make this thread safe for the 1.3 build? I got the impression this was supposed to be thread safe? JuliaCon 2019 | Multi-threading in Julia with PARTR - YouTube ~5mins. I tried both with:
Safe intervals are (1+64*n) : 64*(n+1), and (1+64*n) : end. You would need to cut up your range in a way that all intervals are safe. Do this yourself, such that you get nthreads() many ranges, and then you can run Threads.@threads for ran in ranges. You could read the source code for Threads.@threads and reverse engineer the exact conditions under which it will split up your range in a safe way. However, I recommend against relying on these internals (likely to break in the near future, unmaintainable).
No. You need to change from BitArray{N} to Array{Bool, N}. This is my recommendation for this kind of issue (fill(false, n) instead of falses(n)).