i am struggeling with the usage of the MemLimit (https://www.gurobi.com/documentation/9.5/refman/memlimit.html) option which was newly introduced in Gurobi 9.5.
Gurobi should throw an error when exceeding the given limit and should not continue solving.
Since this Option needs to be set up in the empty environment this cannot be added via the jump function set_optimizer_attribute.
I found a solution to set the this option like this:
using JuMP, Gurobi
env = Gurobi.Env()
Gurobi.GRBsetdblparam(env, "MemLimit", 1.0)
model = Model(() -> Gurobi.Optimizer(env))
# Set the remaining configurations e.g.:
for (k, v) in Dict("Threads" => 3)
set_optimizer_attribute(model, k, v)
end
This code snippet should set up a model with a memory limit of 1 GB for the Optimization. But when i am running a more complex optimization which exceeds this limit Gurobi will just continue solving.
Any idea how i can lookup if i set the option correctly?
which is the default Gurobi value. I could not find out how to set the attribute correctly by trying multiple variations like GRBsetdblattr, GRBsetintparam, GRBsetintattr…
On Gurobi 9.5, this gives me a return code of 10003 and a message of "Unable to modify parameter MemLimit after environment started".
This is consistent with the documentation linked above:
This parameter must be set when the Gurobi environment is first created. You will need to create an empty environment, set the parameter, and then start the environment.
The best option is to put a file called gurobi.env in the working directory that has contents like:
I found a solution. Thanks to @jd-foster I could check if I set the memory limit correctly.
The struggle as you sad is that the environment is already started.
The constructor function in Gurobi would need to be extended to the following for which i already created a pull request in order to set the parameter before the environment is started.
function Env(; output_flag::Int = 1, memory_limit::Number = 1.0e100)
a = Ref{Ptr{Cvoid}}()
ret = GRBemptyenv(a)
env = new(a[], false, 0)
_check_ret(env, ret)
ret = GRBsetintparam(env.ptr_env, GRB_INT_PAR_OUTPUTFLAG, output_flag)
_check_ret(env, ret)
if _GUROBI_VERSION >= v"9.5.0"
ret = GRBsetdblparam(env, GRB_DBL_PAR_MEMLIMIT, memory_limit)
_check_ret(env, ret)
end
ret = GRBstartenv(env.ptr_env)
finalizer(env) do e
e.finalize_called = true
if e.attached_models == 0
# Only finalize the model if there are no models using it.
GRBfreeenv(e.ptr_env)
e.ptr_env = C_NULL
end
end
# Even if the loadenv fails, the pointer is still valid.
_check_ret(env, ret)
return env
end
Since we are working on scaling virtual machines where the memory limit should be variable the usage of an environmental file is not really an option. For a workaround until this the memory limit usage is shipped I found the following to work for me:
env = create_gurobi_env(optimizer.Env(); memlimit = 1.0)
model = Model(() -> optimizer.Optimizer(env))
function create_gurobi_env(env::Gurobi.Env; output_flag::Int = 1, memlimit::Number = 1.0e100)
a = Gurobi.Ref{Ptr{Cvoid}}()
ret = Gurobi.GRBemptyenv(a)
env.ptr_env = a[]
env.finalize_called = false
env.attached_models = 0
Gurobi._check_ret(env, ret)
ret = Gurobi.GRBsetintparam(env.ptr_env, GRB_INT_PAR_OUTPUTFLAG, output_flag)
Gurobi.GRBsetdblparam(env, GRB_DBL_PAR_MEMLIMIT, memlimit)
Gurobi._check_ret(env, ret)
ret = Gurobi.GRBstartenv(env.ptr_env)
Gurobi.finalizer(env) do e
e.finalize_called = true
if e.attached_models == 0
# Only finalize the model if there are no models using it.
Gurobi.GRBfreeenv(e.ptr_env)
e.ptr_env = C_NULL
end
end
# Even if the loadenv fails, the pointer is still valid.
Gurobi._check_ret(env, ret)
return env
end
Since the struct Env cannot be created without the constructor function we need to create an environment first and change the struct to a new one which contains the memory limit.