-
Notifications
You must be signed in to change notification settings - Fork 10
Improved constraint deletion performance by separating functions #95
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! The first version of LQOI wasn't written for performance so there are probably a few of these type of things that could be improved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The latest changes still rely on accessing the internal .vals
field of a dictionary.
Can you benchmark against a naive implementation of:
for (key, value) in scalar
if value > row
scalar[key] -= 1
end
end
Is this really the performance bottleneck when deleting constraints? If so, is this the right fix? Or can we make a larger restructure to sort things out.
for (key,val) in scalar
scalar[key] = val > row ? val - 1 : val
end yields julia> @benchmark constraint_deletion_benchmark(GLPK,1000)
BenchmarkTools.Trial:
memory estimate: 13.62 MiB
allocs estimate: 618630
--------------
minimum time: 91.325 ms (0.00% GC)
median time: 100.139 ms (2.98% GC)
mean time: 101.903 ms (2.03% GC)
maximum time: 128.013 ms (2.51% GC)
--------------
samples: 50
evals/sample: 1 for (key, value) in scalar
if value > row
scalar[key] -= 1
end
end yields julia> @benchmark constraint_deletion_benchmark(GLPK,1000)
BenchmarkTools.Trial:
memory estimate: 21.23 MiB
allocs estimate: 1117130
--------------
minimum time: 139.537 ms (2.12% GC)
median time: 148.302 ms (1.99% GC)
mean time: 151.534 ms (1.93% GC)
maximum time: 173.682 ms (2.35% GC)
--------------
samples: 33
evals/sample: 1 |
Codecov Report
@@ Coverage Diff @@
## master #95 +/- ##
==========================================
- Coverage 90.29% 86.78% -3.51%
==========================================
Files 12 12
Lines 1339 1355 +16
==========================================
- Hits 1209 1176 -33
- Misses 130 179 +49
Continue to review full report at Codecov.
|
Fast deleting is great 6x looks a important improvement. |
What about for (key, value) in scalar
if value > row
scalar[key] = value - 1
end
end This avoids the extra lookup associated with the We've gone from 300ms to 100ms (Great!) (and probably even a little less if we have to perform less If this is a performance issue, I would regard this as a problem in Base Julia. It should provide an exported, documented function that allows querying and setting a key-value pair without having to perform multiple lookups. |
@ndinsmore can cross reference the discourse post? |
This is the discourse post: Which has evolved into the Julia PR: JuliaLang/julia#31223 |
It looks like the PR is gaining enough momentum that it will eventually be added. In the mean time should we implement the naive version? |
Great, thanks for escalating this to Base Julia. Let's implement the naive loop version with a TODO linking to the Julia PR. |
@odow the PR has been merged with master: JuliaLang/julia#31223 |
Slightly related comment: |
Is there anything that is blocking this PR? |
CI is failing. Can we see a before and after benchmark one last time please? |
It is now closer to 10x faster julia> @benchmark constraint_deletion_benchmark(GLPK,1000)
BenchmarkTools.Trial:
memory estimate: 78.49 MiB
allocs estimate: 3863538
--------------
minimum time: 301.017 ms (4.38% GC)
median time: 337.761 ms (4.04% GC)
mean time: 350.259 ms (5.62% GC)
maximum time: 444.934 ms (24.12% GC)
--------------
samples: 15
evals/sample: 1
julia> @benchmark constraint_deletion_benchmark(Clp,1000,(LogLevel=0,))
BenchmarkTools.Trial:
memory estimate: 78.72 MiB
allocs estimate: 3863560
--------------
minimum time: 292.421 ms (3.75% GC)
median time: 320.846 ms (4.76% GC)
mean time: 377.702 ms (8.67% GC)
maximum time: 871.552 ms (29.00% GC)
--------------
samples: 14
evals/sample: 1 row_deletion_perf: julia> @benchmark constraint_deletion_benchmark(GLPK,1000)
BenchmarkTools.Trial:
memory estimate: 5.74 MiB
allocs estimate: 115228
--------------
minimum time: 37.724 ms (0.00% GC)
median time: 42.170 ms (0.00% GC)
mean time: 46.151 ms (4.75% GC)
maximum time: 183.727 ms (0.00% GC)
--------------
samples: 109
evals/sample: 1
julia> @benchmark constraint_deletion_benchmark(Clp,1000,(LogLevel=0,))
BenchmarkTools.Trial:
memory estimate: 5.97 MiB
allocs estimate: 115250
--------------
minimum time: 24.873 ms (0.00% GC)
median time: 29.140 ms (0.00% GC)
mean time: 30.183 ms (4.00% GC)
maximum time: 51.206 ms (10.70% GC)
--------------
samples: 166
evals/sample: 1 |
dict = iter.dict | ||
vals = dict.vals | ||
# @inbounds is here so the it gets propigated to isslotfiled | ||
@inbounds for i = dict.idxfloor:Base.lastindex(vals) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is causing an issue on Julia 0.6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are dropping support for v0.6 does it matter?
Merged despite the failing tests on 0.6 because I just merged a PR bumping Julia to >=1.0. |
Sorry this took so long. |
This change improves the performance of constraint deletion by more than 6x.
Using the following benchmark:
master:
ndinsmore:row_deletion_perf: