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