Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use Ref instead of Array when getting Gurobi parameters #131

Merged
merged 1 commit into from
Jun 24, 2018

Conversation

rdeits
Copy link
Collaborator

@rdeits rdeits commented Jun 24, 2018

Allocating an entire Array is quite expensive and not actually necessary just to be able to pass a reference to a C function. Using a Ref saves 80 bytes of memory on Julia v0.6.3, and I think Julia v0.7 should be able to eliminate the memory allocation entirely.

Before:

julia> @btime Gurobi.get_intattr_old(m, $("NumQNZs"))
  80.248 ns (1 allocation: 96 bytes)
0

After:

julia> @btime Gurobi.get_intattr(m, $("NumQNZs"))
  70.103 ns (1 allocation: 16 bytes)
0

@mlubin mlubin merged commit f54387f into jump-dev:master Jun 24, 2018
@mlubin
Copy link
Member

mlubin commented Jun 24, 2018

Thanks! This code was almost certainly written before Ref existed.

@rdeits
Copy link
Collaborator Author

rdeits commented Jun 24, 2018

Wow, cool 🙂

I'm working on a few more performance improvements--Ideally, I'd like to be able to modify a Gurobi problem in-place without necessarily allocating memory.

@rdeits rdeits deleted the ref-attr branch June 24, 2018 21:56
@odow
Copy link
Member

odow commented Jun 24, 2018

Most of the modification code is wrapped.

If you checkout my MOI branch (#125), then the following example in JuMP should have minimal overhead:
jump-dev/JuMP.jl#1351

I can't remember what the story is in Gurobi with modifying the quadratic terms though. I think it's an add rather than a modify.

@rdeits
Copy link
Collaborator Author

rdeits commented Jun 25, 2018

Thanks! I'm playing around with that branch now. I've tried some of the problem modification stuff, but there are a few places inside the API that are allocating memory. For example, this line: https://github.com/JuliaOpt/Gurobi.jl/blob/f54387f47a939a8b8e01c4cc74882f729b5317be/src/grb_quad.jl#L26 copies all of the Vector{Int}s to Vector{Cint}, and then this line: https://github.com/JuliaOpt/Gurobi.jl/blob/f54387f47a939a8b8e01c4cc74882f729b5317be/src/grb_quad.jl#L16 allocates new arrays to hold the 0-based indices.

Getting rid of the allocation for the zero-based indices is easy, because we can just subtract 1 in-place and then put it back, but the Int32 allocation is trickier. One thing I'm considering is a possibly crazy idea to do the conversion in-place (since we can fit two Int32s inside an Int64) and then putting them back at the end: https://gist.github.com/rdeits/db130355fc55c72b6827f9c6371ce288

@mlubin
Copy link
Member

mlubin commented Jun 25, 2018

One thing I'm considering is a possibly crazy idea to do the conversion in-place (since we can fit two Int32s inside an Int64) and then putting them back at the end:

What about storing an extra Vector{Cint} or two in the model object and copying the coefficients over? They can be resized on occasion if needed, still eliminating most allocations if there are lots of modifications.

@rdeits
Copy link
Collaborator Author

rdeits commented Jun 25, 2018

That's also a good idea and substantially less crazy than what I was proposing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants