I’m very curious here. Where can this API lead to allocations so that it has even more allocations that @objective (in number of allocations, though not in total memory size) when I want to reset the objective function?
@odow Could you explain the detailed procedures related to these two methods? e.g. the macro would construct a JuMP expression as an intermediate object…
import JuMP
incre(m, x, c) = for (x, c) = zip(x, c)
JuMP.set_objective_coefficient(m, x, c)
end
function test(m, N, c)
JuMP.@variable(m, x[1:N])
JuMP.@objective(m, Min, 0)
@time incre(m, x, c)
@time JuMP.@objective(m, Min, c'x)
end
N = 300
m = Settings.Model();
test(m, N, rand(N));
# results:
0.000150 seconds (900 allocations: 23.438 KiB)
0.000055 seconds (60 allocations: 53.250 KiB)
# The incremental method takes longer time
# And more number of allocations (900 vs 60)
# Though the 23 KiB is fewer
The Settings is a module that I wrote. You can replace with a JuMP.direct_model(Gurobi), I guess it’s the same.
There’s a dynamic dispatch in set_objective_coefficient that depends on the objective function type. You can get around it by using the vector version:
julia> using JuMP
julia> incre(m, x, c) = for (x, c) = zip(x, c)
JuMP.set_objective_coefficient(m, x, c)
end
incre (generic function with 1 method)
julia> N = 300
300
julia> c = rand(N);
julia> model = Model();
julia> @variable(model, x[1:N]);
julia> @objective(model, Min, 0)
0
julia> @time incre(model, x, c);
0.005044 seconds (11.15 k allocations: 538.391 KiB, 96.98% compilation time)
julia> @time set_objective_coefficient(model, x, c);
0.000085 seconds (27 allocations: 8.500 KiB)
julia> @time @objective(model, Min, c'x);
0.000059 seconds (113 allocations: 59.844 KiB)
Note that some allocations when modifying an objective coefficient are irrelevant in practice.
If you need a non-allocating version, you can use MOI directly, assume a fixed objective type, etc. JuMP makes things easy from a user.