Type inference with threads

I’m wondering if there is something I’m doing wrong that’s preventing the compiler from figuring out the type of an array I am trying to return with multi-threading. I have a small example here:

function testtype(x::Int64)
  outp::Array{Int64,1} = zeros(Int64, x)
  Threads.@threads for i = 1:x
    outp[i] = i
  end
end

@code_warntype testtype(1);
Variables:
  #self#::#testtype
  x::Int64
  outp::Core.Box
  ##_threadsfor#286::##262###_threadsfor#286#36{Int64}
... (omitted the rest) ... 

vs.

function testtype2(x::Int64)
  outp::Array{Int64,1} = zeros(Int64, x)
  for i = 1:x # no threading
    outp[i] = i
  end
end

@code_warntype testtype2(1);
Variables:
  #self#::#testtype2
  x::Int64
  outp::Array{Int64,1}
  #temp#::Int64
  i::Int64
... (omitted the rest) ... 

I don’t know if this is negatively impacting performance in my (more complicated) actual case, but I was surprised that I couldn’t convince the compiler of the type of the vector outp even with an explicit declaration. Is this a known feature of multi-threading and is there a way around it? (Or should I not worry about it?)

versioninfo()
Julia Version 0.5.0
Commit 3c9d753 (2016-09-19 18:14 UTC)
Platform Info:
  System: Darwin (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.7.1 (ORCJIT, broadwell)

This is performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub. See workaround mentioned in there.

If anyone is looking for a solution to this problem in the future, one workaround seems to be this kind of thing:

function testtype3(x::Int64)
  outp::Array{Int64,1} = zeros(Int64,x)
  dothread(outp)
  return outp 
end

function dothread(x)
  Threads.@threads for i = 1:length(x)
    x[i] = i
  end
end

@code_warntype testtype3(1);

Variables:
  #self#::#testtype3
  x::Int64
  outp::Array{Int64,1}
  ##_threadsfor#282::##257###_threadsfor#282#32{Array{Int64,1}}
...

Putting the Thread.@threads part in a separate function removes the problem, as far as I can tell.

This solution is used here.

1 Like