# Help with Performance in JuMP

**URL:** <https://discourse.julialang.org/t/help-with-performance-in-jump/57874>\
**Category:** Optimization (Mathematical)\
**Tags:** jump, performance, optimization\
**Created:** [March 24, 2021, 3:04pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874 "2021-03-24T15:04:29Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![jmcastro2109](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmcastro2109/32/38427_2.png) [@jmcastro2109](https://discourse.julialang.org/u/jmcastro2109)\
**Post date:** [March 24, 2021, 3:04pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/1 "2021-03-24T15:04:29Z")

</div>

Hi,

I am trying to solve a maximization problem using Gurobi/JuMP and I would really appreciate it if you could help me speed things up. Some background on the problem, essentially I am trying to maximize the expectation of a function by sampling it. I am going to find the solution for every sampled outcome, and then I am going to force the solutions to be the same (nonanticipativity constraint).

I am sampling K different outcomes of the random variable which in the example is price and solving

\max\_{I(\omega^{k})\forall k} \frac{1}{K} \sum\_{k=1}^{K} F(I(\omega^{k}),\omega^{k})

subject to

I(\omega^{1})=I(\omega^{2})=I(\omega^{3})=\cdots=I(\omega^{K})

This is a MWE of the problem:

```julia
using DelimitedFiles,DataFrames,GLM,FixedEffects, ExcelReaders, LinearAlgebra, Random
using Distributions, BitOperations
using Discretizers,Plots
using JuMP, Gurobi, BenchmarkTools

###############################################################
# AUX FUNCTIONS
###############################################################

###############################################################
# Generating Data
###############################################################

#Model Parameters

J=67 #number of nodes#
K = 500

price=rand(J,K)
F=rand(J)

function problem_iter(price,σ,K,F)
	price = price.^(1-σ)
	model = Model(Gurobi.Optimizer)
	@variable(model, I[1:J,1:K], Bin)
	@variable(model, Ipost[1:J,1:K], Bin)

	set_silent(model)

	# Objective Function

	@objective(model, Max, 1/K*(sum( (price[:,k]'*Ipost[:,k]) - F'*I[:,k] for k=1:K)))

	# Constraint 1 and 2 - non-anticipativity constraint and ex-post choice
	for k=1:K
		@constraint(model, I[:,k] .== sum(I,dims=2)/K)
		@constraint(model, Ipost[:,k]'*Ipost[:,k] == 1)
		@constraint(model, sum(Ipost[:,k].*I[:,k] ) == 1)
	end

	optimize!(model)

	Iᵒ = value.(I)
	Iᵒ = trunc.(Int,Iᵒ)
	Ipost = value.(Ipost)
	Ipost = trunc.(Int,Ipost)

	return Iᵒ, Ipost
end

TEST=@time problem_iter(price,2,K,F)

```

I am getting the following warning that for sure is diminishing performance, but I am not sure on how to handle

```julia
┌ Warning: The addition operator has been used on JuMP expressions a large number of times. This warning is safe to ignore but may indicate that model generation is slower than necessary. For performance reasons, you should not add expressions in a loop. Instead of x += y, use add_to_expression!(x,y) to modify x in place. If y is a single variable, you may also 
use add_to_expression!(x, coef, y) for x += coef*y.

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 24, 2021, 3:30pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/2 "2021-03-24T15:30:36Z")

</div>

I think the first thing you could do is to put prints before each JuMP command so you can check when the message is triggered. If it is in the `@objective`, at a `@constraint`, or only at the `optimize!` (what can, unfortunately, be the case if these calls are deferred to just before they are really necessary). If this does not help to pinpoint the origin of the problem, I would comment out things one by one until the message disappears.

---

<div class="post-metadata">

**Author:** ![jmcastro2109](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmcastro2109/32/38427_2.png) [@jmcastro2109](https://discourse.julialang.org/u/jmcastro2109)\
**Post date:** [March 24, 2021, 3:57pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/3 "2021-03-24T15:57:17Z")

</div>

Hi @Henrique_Becker, apparently it is on the Objective! Any suggestions?

Nonetheless, it seems to me that the bulk of the time is being spent on the constraints.

---

<div class="post-metadata">

**Author:** ![jmcastro2109](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmcastro2109/32/38427_2.png) [@jmcastro2109](https://discourse.julialang.org/u/jmcastro2109)\
**Post date:** [March 24, 2021, 4:17pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/4 "2021-03-24T16:17:44Z")

</div>

Using the following makes it much faster,

```julia
#Model Parameters

J=67 #number of nodes#
K = 10000

price=rand(J,K)
F=rand(J)

function problem_iter(price,σ,K,F)
	price = price.^(1-σ)
	model = Model(Gurobi.Optimizer)
	@variable(model, I[1:J,1:K], Bin)
	@variable(model, Ipost[1:J,1:K], Bin)
	@variable(model, Itrue[1:J])

	set_silent(model)

	# Objective Function

	println("Objective")
	@objective(model, Max, 1/K*(sum( (price[:,k]'*Ipost[:,k]) - F'*I[:,k] for k=1:K)))

	println("Constraints")
	# Constraint 1 and 2 - non-anticipativity constraint and ex-post choice
	for k=1:K
		@constraint(model, I[:,k] .== Itrue)
		@constraint(model, Ipost[:,k]'*Ipost[:,k] == 1)
		@constraint(model, sum(Ipost[:,k].*I[:,k] ) == 1)
	end

	println("Optimize")
	optimize!(model)

	Iᵒ = value.(I)
	Iᵒ = trunc.(Int,Iᵒ)
	Ipost = value.(Ipost)
	Ipost = trunc.(Int,Ipost)
	Iopt = value.(Itrue)

	return Iᵒ, Ipost, trunc.(Int,Iopt)
end

TEST=@time problem_iter(price,2,K,F)

```

Still any suggestions on how to make this faster are more than welcome!

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [March 24, 2021, 5:51pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/5 "2021-03-24T17:51:18Z")

</div>

I was not able to spot the difference, what did you change?

I think one thing that may help performance (but I did not test it) is not referring to global variables. `K` is fine in your example because you are referring to the `K` that you get by parameter (even if the value is the same bound to a global variable) but `J` and `F` are used inside the function too, but not received by parameter, what can cause serious performance problems. [Avoid global variables](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-global-variables) is literally the first tip on the Performance Tips section of the manual. If you cannot pass them by parameter you should at least make them `const` (like in `const J = 67`), and never change them.

---

<div class="post-metadata">

**Author:** ![jmcastro2109](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmcastro2109/32/38427_2.png) [@jmcastro2109](https://discourse.julialang.org/u/jmcastro2109)\
**Post date:** [March 24, 2021, 6:03pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/6 "2021-03-24T18:03:18Z")

</div>

I created a new auxiliary variable named Itrue, and replaced it for the sum of I[:,k] which I was computing at each iteration.

Yes, will take a look at that. Thanks!

---

<div class="post-metadata">

**Author:** ![jmcastro2109](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmcastro2109/32/38427_2.png) [@jmcastro2109](https://discourse.julialang.org/u/jmcastro2109)\
**Post date:** [March 25, 2021, 12:44pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/7 "2021-03-25T12:44:37Z")

</div>

Does anyone have any further suggestions?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 25, 2021, 7:14pm UTC](https://discourse.julialang.org/t/help-with-performance-in-jump/57874/8 "2021-03-25T19:14:40Z")

</div>

Why do you need `I` and `Itrue`? I think you just need something like the following:

```nohighlight
using JuMP
function problem_iter(price,σ,K,F)
	price = price.^(1-σ)
	model = Model()
	@variable(model, Ipost[1:J, 1:K], Bin)
	@variable(model, Itrue[1:J], Bin)
	set_silent(model)
	@objective(
        model, 
        Max, 
        1/K * sum(price[j, k] * Ipost[j, k] - F[j] * Itrue[j] for j = 1:J, k = 1:K)
    )
	for k=1:K
		@constraint(model, sum(Ipost[j, k] * Ipost[j, k] for j = 1:J) == 1)
		@constraint(model, sum(Ipost[j, k] * Itrue[j] for j = 1:J) == 1)
	end
    return model
end

J=67
K = 10000
price=rand(J,K)
F=rand(J)
TEST=@time problem_iter(price,2,K,F)

```
