So, I think I have a MWE (and it is a strange type-instability):
Copy and past the code below, and you will see that running:
run()
will result in a type instability, or not, depending on these lines of the test
function:
reduce!(list, list_threaded) # type stable
#list = reduce!(list, list_threaded) # type unstable
The problem is inferring the type of list
. Because it is mutable, and reduce
also returns list
, both calls above should be equivalent (and they are except if using @threads
).
Thus, removing the reassignment of list
on the return of reduce
solves the problem. Except that the reason I am using that is that by doing that I can use the same function to operate on mutable or immutable list
variables. If I remove the reassignment, I cannot use the same interface to operate on immutables. In any case, seems an issue the fact that this is affected by the use of @threads
in some other part of the code.
The example:
function reduce!(list,list_threaded)
list .= list[1]
for i in 2:length(list_threaded)
list .+= list_threaded[i]
end
return list
end
function test(list,list_threaded)
#for it in 1:Threads.nthreads() # type stable
Threads.@threads for it in 1:Threads.nthreads()
for i in it:Threads.nthreads():length(list)
list_threaded[it][i] += rand()
end
end
#reduce!(list, list_threaded) # type stable
list = reduce!(list, list_threaded) # type unstable
return list
end
function run()
list = zeros(10^4)
list_threaded = [ copy(list) for _ in 1:Threads.nthreads() ]
@code_warntype test(list, list_threaded)
end