Skip to content

Add type parameter for CachingOptimizer #390

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

Merged
merged 5 commits into from
Jun 17, 2018
Merged

Add type parameter for CachingOptimizer #390

merged 5 commits into from
Jun 17, 2018

Conversation

blegat
Copy link
Member

@blegat blegat commented Jun 14, 2018

This PR adds a type parameter for the optimizer of CachingOptimizer. It adds this type parameters in the first place as it will be more useful than the second one (see e.g. dropoptimizer!). It also changes the order of the cache and the optimizer fields for consistency.
Note that it does not implement the idea of #321 (comment) of removing the possibility to have no optimizer or to change the optimizer.
Indeed, this would require JuMP to handle these cases and I initially thought that this was the solution because I didn't have the idea of simply using the non concrete type parameter Union{Nothing, MOI.AbstractOptimizer} in the case where we want to be able to drop the optimizer and to change it and use the concrete optimizer type when we don't want to change it and the type instability becomes the bottleneck (e.g. #321).

We can now make a similar change in JuMP. Have a parameter for the moibackend type that the user can set it to the concrete type of the optimizer to have no overhead (but loosing the features of changing optimizer, droping it, ...)

Benchmarks

See #323 for benchmarks before this change

With a CachingOptimizer with concrete field type for the optimizer field (i.e. MockOptimizer{Model{Float64}}):

v0.6
 36.591 ns (4 allocations: 112 bytes)
148.012 ns (8 allocations: 224 bytes)
 24.322 ns (3 allocations: 96 bytes)
 24.871 ns (3 allocations: 96 bytes)
v0.7
 12.130 ns (1 allocation: 48 bytes)
103.417 ns (3 allocations: 112 bytes)
 13.545 ns (1 allocation: 48 bytes)
 11.785 ns

With a CachingOptimizer with Union{Nothing, OptimizerType} with concrete OptimizerType for the `optimizer field:

v0.6
 40.083 ns (4 allocations: 112 bytes)
177.939 ns (11 allocations: 288 bytes)
 29.122 ns (3 allocations: 96 bytes)
 25.401 ns (3 allocations: 96 bytes)
v0.7
 13.049 ns (1 allocation: 48 bytes)
109.670 ns (3 allocations: 112 bytes)
 11.501 ns (1 allocation: 48 bytes)
 12.421 ns (1 allocation: 48 bytes)

The overhead of the union with Void is negligible in v0.7 as suggested by #390 (comment) so it seems cleaner to use it

Closes #321

@codecov-io
Copy link

codecov-io commented Jun 14, 2018

Codecov Report

Merging #390 into master will increase coverage by 0.27%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #390      +/-   ##
==========================================
+ Coverage   96.48%   96.75%   +0.27%     
==========================================
  Files          39       39              
  Lines        4917     5397     +480     
==========================================
+ Hits         4744     5222     +478     
- Misses        173      175       +2
Impacted Files Coverage Δ
src/Utilities/cachingoptimizer.jl 87.74% <100%> (-0.58%) ⬇️
src/sets.jl 90% <0%> (-10%) ⬇️
src/functions.jl 100% <0%> (ø) ⬆️
src/Test/contconic.jl 100% <0%> (ø) ⬆️
src/Utilities/functions.jl 98.82% <0%> (+1.96%) ⬆️
src/Utilities/mockoptimizer.jl 99.48% <0%> (+2.01%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dc47126...3f4db45. Read the comment docs.

@@ -22,9 +22,9 @@ A `CachingOptimizer` has two modes of operation (`CachingOptimizerMode`):
- `Manual`: The only methods that change the state of the `CachingOptimizer` are [`resetoptimizer!`](@ref), [`dropoptimizer!`](@ref), and [`attachoptimizer!`](@ref). Attempting to perform an operation in the incorrect state results in an error.
- `Automatic`: The `CachingOptimizer` changes its state when necessary. For example, `optimize!` will automatically call `attachoptimizer!` (an optimizer must have been previously set). Attempting to add a constraint or perform a modification not supported by the optimizer results in a drop to `EmptyOptimizer` mode.
"""
mutable struct CachingOptimizer{MT<:MOI.ModelLike} <: MOI.AbstractOptimizer
mutable struct CachingOptimizer{OT, MT<:MOI.ModelLike} <: MOI.AbstractOptimizer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try more explicit names for the type parameters. Something like OptimizerType and ModelType maybe?

@@ -34,19 +34,24 @@ mutable struct CachingOptimizer{MT<:MOI.ModelLike} <: MOI.AbstractOptimizer
# optimizer indices.
end

CachingOptimizer(model_cache::MOI.ModelLike, mode::CachingOptimizerMode) = CachingOptimizer(model_cache, nothing, NoOptimizer, mode, IndexMap(), IndexMap())
function CachingOptimizer(model_cache::MOI.ModelLike, mode::CachingOptimizerMode)
CachingOptimizer{Union{Nothing,MOI.AbstractOptimizer}, typeof(model_cache)}(nothing, model_cache, NoOptimizer, mode, IndexMap(), IndexMap())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Union{Nothing,MOI.AbstractOptimizer} is a really unusual type parameter. Why not type the optimizer as Union{Nothing, OptimizerType}? My understanding is that there's very little overhead in 0.7 for Union{Nothing, T} if T is concrete.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, I have updated the description which a benchmark showing this

`CachingOptimizer`-specific functions (e.g. `dropoptimizer!`) are called on it.
`CachingOptimizer`-specific functions (e.g. `resetoptimizer!`) are called on it.
The type of the optimizer returned is `CachingOptimizer{typeof(optimizer),
typeof(model_cache)}` so it does not support the function `dropoptimizer!`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it does not support the function dropoptimizer! nor the method `resetoptimizer!.

Is this true? Can't the field be set to nothing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, fixed :)

@blegat blegat force-pushed the bl/cachingoptOT branch from 0cc5378 to a70059c Compare June 17, 2018 08:53
model_cache::MT
optimizer::Union{Nothing,MOI.AbstractOptimizer}
mutable struct CachingOptimizer{OptimizerType, ModelType<:MOI.ModelLike} <: MOI.AbstractOptimizer
optimizer::OptimizerType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you plan to update this to optimizer::Union{OptimizerType, Nothing}?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ups, fixed

@blegat blegat force-pushed the bl/cachingoptOT branch from a70059c to 3f4db45 Compare June 17, 2018 18:08
@blegat blegat merged commit 1e30cfe into master Jun 17, 2018
@blegat blegat deleted the bl/cachingoptOT branch August 28, 2018 14:32
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