Unexpected 4x slowdown when computing many svds in loop

I compute svds of N roughly ~100x100 matrices and note a 4x slowdown when I do this in a loop for N > 100.

function f_svd(n::Int64,a::Array{Float64,2})
     for i in 1:n
          u,s,v = svd(a);
     end
 end

(in my real code I compute svds of different matrices and store away results).

using BenchmarkTools
using LinearAlgebra
a = rand(100,100)
@btime f_svd($1,$a);
@btime f_svd($10,$a);
@btime f_svd($100,$a);   
@btime f_svd($1000,$a);

3.101 ms (16 allocations: 482.02 KiB)
64.479 ms (160 allocations: 4.71 MiB)
1.317 s (1600 allocations: 47.07 MiB)
13.964 s (16000 allocations: 470.72 MiB)

Note that the time for n = 10 is roughly 2 x 10 x (time for n = 1). The time for n = 100 is roughly 4 x 100 x (time for n = 1). Beyond n = 100 the extra slowdown is minimal.

Is this effect purely due to the processors having a hard time swapping data in and out of memory, or is there a Julia trick i can use to speed up my code (by roughly a factor of 4)?

julia> @btime f_svd($1,$a);
  3.181 ms (12 allocations: 481.95 KiB)

julia> @btime f_svd($10,$a);
  35.871 ms (120 allocations: 4.71 MiB)

julia> @btime f_svd($100,$a);
  487.371 ms (1200 allocations: 47.07 MiB)

julia> @btime f_svd($1000,$a);
  5.105 s (12000 allocations: 470.66 MiB)

julia> versioninfo()
Julia Version 1.1.1
Commit 55e36cc308 (2019-05-16 04:10 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 4

Are you using Laptop?
If you do, it might be a CPU throttling happening when you stress the CPU for longer time.

I am using Juliabox:

versioninfo()

Julia Version 1.0.3
Commit 099e826241 (2018-12-18 01:34 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel® Xeon® CPU E5-2673 v4 @ 2.30GHz
WORD_SIZE: 64
LIBM: libopenlibm LLVM: libLLVM-6.0.0 (ORCJIT, broadwell)
Environment:
JULIABOX = true
JULIA_PKG_SERVER = https://pkg.juliacomputing.com
JULIA = /opt/julia-0.6/bin/julia JULIA_KERNELS = [‘julia-0.6’, ‘julia-1.0’, ‘julia-1.0k’]
JULIA_PKG_TOKEN_PATH = /mnt/juliabox/.julia/token.toml JULIABOX_ROLE =
JULIA_NUM_THREADS = 4

Probably not a good platform for benchmarking.

3 Likes