title: Slower times in multithreading using Julia 1.3.1
body: <p>I started recently using the new multithreading interface in the 1.3.1 version. After I tried the fibonacci example <a href="https://julialang.org/blog/2019/07/multithreading" rel="nofollow noreferrer">in this blog post</a> and getting significant speedups, I started experimenting with some old algorithms of mine.</p>
  
  <p>I have a function that uses the trapezoid method to calculate integrals, both below or above a curve:</p>
  
  <pre><code>function trapezoid( x    :: AbstractVector       ,
                      y    :: AbstractVector       ;
                      y0   :: Number         = 0.0 ,
                      inv  :: Number         = NaN )
     int = zeros(length(x)-1)
     for i = 2:length(x)
        if isnan(inv) == true
           int[i-1] = (y[i]+y[i-1]-2y0) * (x[i]-x[i-1]) / 2
        else
           int[i-1] = (2inv-(y[i]+y[i-1])-2y0) * (x[i]-x[i-1]) / 2
        end # if
     end # for
     integral = sum(int) ;
     return integral
  end
  </code></pre>
  
  <p>Then I have a very inefficient algorithm that determines the midpoint index of a curve comparing the area below and above the curve:</p>
  
  <pre><code>function EAM_without_threads( x     :: Vector{Float64} ,
                                y     :: Vector{Float64} ,
                                y0    :: Real            ,
                                ymean :: Real            )
  
      approx = Vector{Float64}(undef,length(x)-1)
      for i in 1:length(x)-1
          x1 = @view(x[1:i  ])
          x2 = @view(x[i:end])
          y1 = @view(y[1:i  ])
          y2 = @view(y[i:end])
          Al = trapezoid( x1 , y1 , y0=y0     )
          Au = trapezoid( x2 , y2 , inv=ymean )
  
          approx[i] = abs(Al-Au)
      end
      minind = findmin(approx)[2]
  
      return x[minind]
  end
  </code></pre>
  
  <p>And:</p>
  
  <pre><code>function EAM_with_threads( x     :: Vector{Float64} ,
                             y     :: Vector{Float64} ,
                             y0    :: Real            ,
                             ymean :: Real            )
  
      approx = Vector{Float64}(undef,length(x)-1)
      for i in 1:length(x)-1
          x1 = @view(x[1:i  ])
          x2 = @view(x[i:end])
          y1 = @view(y[1:i  ])
          y2 = @view(y[i:end])
          Al = @spawn trapezoid( x1 , y1 , y0=y0     )
          Au = @spawn trapezoid( x2 , y2 , inv=ymean )
  
          approx[i] = abs(fetch(Al)-fetch(Au))
      end
      minind = findmin(approx)[2]
  
      return x[minind]
  end
  </code></pre>
  
  <p>This is what I used to try both functions:</p>
  
  <pre><code>using SpecialFunctions
  using BenchmarkTools
  
  x = collect(-10.0:5e-4:10.0)
  y = erf.(x)
  </code></pre>
  
  <p>And then got these results:</p>
  
  <pre><code>julia&gt; @btime EAM_without_threads(x,y,-1.0,1.0)
    7.515 s (315905 allocations: 11.94 GiB)
  
  julia&gt; @btime EAM_with_threads(x,y,-1.0,1.0)
    10.295 s (1274131 allocations: 12.00 GiB)
  </code></pre>
  
  <p>I don't understand... Using <code>htop</code> I can see that all my 8 threads are working almost at full capacity. This is my machine:</p>
  
  <pre><code>julia&gt; versioninfo()
  Julia Version 1.3.1
  Commit 2d5741174c (2019-12-30 21:36 UTC)
  Platform Info:
    OS: Linux (x86_64-pc-linux-gnu)
    CPU: Intel(R) Core(TM) i7-4712MQ CPU @ 2.30GHz
    WORD_SIZE: 64
    LIBM: libopenlibm
    LLVM: libLLVM-6.0.1 (ORCJIT, haswell)
  Environment:
    JULIA_NUM_THREADS = 8
  </code></pre>
  
  <p>I know about the overhead of dealing with several threads, and in small problems I understand if it's slower, but why in this case?</p>
  
  <p>I'm also searching for multithreading "good practices", because I guess not every piece of code will benefit from parallelism.</p>
  
  <p>Thank you all in advance.</p>