# Convex.jl (+SCS) more than 100\* slower than R counterpart, CVXR + SCS

**URL:** <https://discourse.julialang.org/t/convex-jl-scs-more-than-100-slower-than-r-counterpart-cvxr-scs/31717>\
**Category:** Optimization (Mathematical)\
**Tags:** performance\
**Created:** [December 1, 2019, 6:17pm UTC](https://discourse.julialang.org/t/convex-jl-scs-more-than-100-slower-than-r-counterpart-cvxr-scs/31717 "2019-12-01T18:17:53Z")\
**Posts on this page:** 1\
**Showing post:** 8

<div class="post-metadata">

**Author:** ![reumle](https://avatars.discourse-cdn.com/v4/letter/r/5daacb/32.png) [@reumle](https://discourse.julialang.org/u/reumle)\
**Post date:** [December 2, 2019, 12:32am UTC](https://discourse.julialang.org/t/convex-jl-scs-more-than-100-slower-than-r-counterpart-cvxr-scs/31717/8 "2019-12-02T00:32:32Z")

</div>

Eric, thanks a lot for the detailed and useful feedback. I ran your code, which ensured exactly the same data were being used Julia-side and R-side. Tonight I just wanted to establish a Baseline, and I will run newer versions of convex tomorrow.

Essentially the timing difference [convex vs CVXR] remains (more or less) unchanged, and also scaling still looks quadratic.

### timings (all in secs)

- Julia  
You see a first run with 200 rows in order to compile all functions, and then 3 independent runs:

```julia-auto
13×4 DataFrame
│ Row │ n │ m │ setupTm │ solveTm │
│ │ Int64 │ Int64 │ Float64 │ Float64 │
├─────┼───────┼───────┼─────────┼─────────┤
│ 1 │ 36 │ 200 │ 0.001 │ 0.059 │
│ 2 │ 36 │ 200 │ 0.0 │ 0.058 │
│ 3 │ 36 │ 1000 │ 0.0 │ 1.256 │
│ 4 │ 36 │ 5000 │ 0.0 │ 45.586 │
│ 5 │ 36 │ 10000 │ 0.0 │ 218.275 │
│ 6 │ 36 │ 200 │ 0.0 │ 0.062 │
│ 7 │ 36 │ 1000 │ 0.0 │ 1.257 │
│ 8 │ 36 │ 5000 │ 0.0 │ 46.429 │
│ 9 │ 36 │ 10000 │ 0.0 │ 210.443 │
│ 10 │ 36 │ 200 │ 0.001 │ 0.061 │
│ 11 │ 36 │ 1000 │ 0.0 │ 1.27 │
│ 12 │ 36 │ 5000 │ 0.0 │ 46.037 │
│ 13 │ 36 │ 10000 │ 0.0 │ 267.79 │

```

- R/CVXR

```julia-auto
> df3
# A tibble: 12 x 5
    nCol nRow moment setupTm solveTm
   <dbl> <dbl> <dttm> <dbl> <dbl>
 1 36 200 2019-12-02 00:16:45 0.0509 0.0429
 2 36 1000 2019-12-02 00:16:45 0.0329 0.0738
 3 36 5000 2019-12-02 00:16:45 0.0299 0.311 
 4 36 10000 2019-12-02 00:16:46 0.0309 0.923 
 5 36 200 2019-12-02 00:16:47 0.0299 0.0319
 6 36 1000 2019-12-02 00:16:47 0.0409 0.0768
 7 36 5000 2019-12-02 00:16:47 0.0329 0.292 
 8 36 10000 2019-12-02 00:16:48 0.0299 0.845 
 9 36 200 2019-12-02 00:16:49 0.0270 0.0309
10 36 1000 2019-12-02 00:16:49 0.0278 0.0628
11 36 5000 2019-12-02 00:16:49 0.0339 0.295 
12 36 10000 2019-12-02 00:16:50 0.0299 0.653 

```

### code

- Julia  
I ran your code but with a change. In order to keep it comparable to the previous version and also to R I did not use `@belapsed`, and kept using the `Dates.now()` function.

The part which I modified is the final loop. The rest is unchanged. Please find it below.

```julia-auto
using DelimitedFiles, DataFrames, BenchmarkTools

n = 36
for m in [200,1000,5000,10000]
	A = randn(m,n)
	b = randn(m)
	writedlm("n=$(n)_m=$(m)_A.txt", A)  
	writedlm("n=$(n)_m=$(m)_b.txt", b)  
end

function setup_problem(A, b)
	m, n = size(A)
	s = Variable(m)
  	x = Variable(n)
  	p = minimize(sum(s), [A*x - b <= s, A*x - b >= -s, x>-10, x< 10, sum(x) >10])
end

function solve_problem(p)
	solver = SCSSolver(linear_solver= SCS.Direct, max_iters= 10, verbose=false)
	solve!(p, solver; verbose = false)
end

df= DataFrame(n = Int64[], m = Int64[], setupTm=Float64[], solveTm=Float64[])
df2= DataFrame(n = Int64[], m = Int64[], setupTm=Float64[], solveTm=Float64[])

for m in [200,1000,5000,10000]
#	for m in [200]
 	A = readdlm("n=$(n)_m=$(m)_A.txt")
	b = readdlm("n=$(n)_m=$(m)_b.txt")  

	moment1=Dates.now()
	p=setup_problem(A, b)
	moment2= Dates.now()
	
	q = solve_problem(p)
	moment3=Dates.now()
	push!(df2, [n, m, Dates.value(moment2-moment1)/1000, Dates.value(moment3-moment2)/1000])

end

```

- R/CVXR code. Reads Julia txt output for A and b.

```julia-auto
library("scs")	
library("CVXR")	
library("tibble")
library("dplyr")

df3=tibble(nCol=numeric(),nRow=numeric(),moment=as.POSIXct(character()),setupTm=numeric(),solveTm=numeric())
#for (bscale in c(0.1,0.3,1,2))
for (nRow in c(200,1000,5000,10000)){

nCol=36

fDir="C:\\Users\\elm\\.atom\\"

fName=paste0(fDir,"n=",nCol,"_m=",nRow,"_A.txt")
AA = as.matrix(read.table(file=fName,header=FALSE))

fName=paste0(fDir,"n=",nCol,"_m=",nRow,"_b.txt")
b = as.matrix(read.table(file=fName,header=FALSE))

moment1=Sys.time()

s <- Variable( nrow( AA)) 
x <- Variable( ncol( AA))

objective1 = Minimize( sum(s) )
constraints = list( x< 10, x > -10,
	                     AA %*% x - b <= s,
	                     AA %*% x - b >= -s,
	                     sum( x) > 10)

prob1 = Problem( objective1, constraints)	
	

moment2 = Sys.time()
solut2	=	psolve( prob1,verbose=TRUE,solver="SCS",max_iters=10,warm_start=FALSE)	
#	sc_a =	solut1$getValue(a)
moment3 = Sys.time()

df3=df3 %>% add_row(nCol=nCol,nRow=nRow,moment=moment1,setupTm=moment2-moment1,solveTm=moment3-moment2)
}

```

Thanks again.  
Emmanuel.  
PS your code calls `setup_problem` twice? Is it intended? (I am a beginner in Julia)  
PPS current package versions, hardware info.

```julia-auto
julia> pkgs
"Convex" => v"0.12.5"
…
"SCS" => v"0.6.2"
…

julia> VERSION
v"1.2.0"

julia> Sys.cpu_summary()
Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz:

julia> Sys.windows_version()
v"10.0.17763"

```

---

_[View the full topic](https://discourse.julialang.org/t/convex-jl-scs-more-than-100-slower-than-r-counterpart-cvxr-scs/31717)._
