[tune] Use generic _ObjectCache for actor reuse - #33045
Conversation
Signed-off-by: Kai Fricke <coding@kaifricke.com>
Signed-off-by: Kai Fricke <coding@kaifricke.com>
Signed-off-by: Kai Fricke <coding@kaifricke.com>
justinvyu
left a comment
There was a problem hiding this comment.
Looks good! I added a few questions/clarifications.
The eager_caching flag and keep_one logic seems a bit custom tailored to this specific Tune controller loop - is there a way to make it more general? One idea I had was to make this keep_at_least=1 instead. We don't need to over-generalize though, since I'm not too sure where we can use this _ObjectCache in other places in Tune. Any ideas there?
|
|
||
| while len(objs) > max: | ||
| self._num_cached_objects -= 1 | ||
| yield objs.pop(0) |
There was a problem hiding this comment.
Do we want to pop all first, then yield the results? Or is popping as we go intended behavior?
If we break/return in the middle of handling the result, some of the objects we tried to flush will still be in there.
There was a problem hiding this comment.
I think that's what we want. The caller may have to run cleanup on the objects, and if we pop them first and fail, the objects are lost and we may end up with leaked objects.
|
Yeah I agree that this is pretty specific to Tune's needs. The main two reasons to separate this out are 1) better unit testability (currently the reuse logic is happening fully within Trial Executor logic) and 2) reuse in the refactoring towards the Tune Controller (to avoid too much code duplication). I'd propose we leave it as is (i.e. keep eager caching for exactly one unit) and if we actually reuse this in a different component with different requirements, we can change it then. Ok? |
Signed-off-by: Kai Fricke <kai@anyscale.com>
Signed-off-by: Kai Fricke <kai@anyscale.com>
justinvyu
left a comment
There was a problem hiding this comment.
Makes sense, looks good to me!
xwjiang2010
left a comment
There was a problem hiding this comment.
sorry just one more comment :)
|
The failure in test_commands seems unrelated to this issue and comes up for me locally on master as well. It's due to extensive rllib imports. I'll merge this PR |
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests). By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected. Signed-off-by: Kai Fricke <coding@kaifricke.com> Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: Jack He <jackhe2345@gmail.com>
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests). By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected. Signed-off-by: Kai Fricke <coding@kaifricke.com> Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: Edward Oakes <ed.nmi.oakes@gmail.com>
Similar regression that was originally fixed in #31974, but re-surfaced after #33045. With actor re-use, we speculatively keep one cached actor around in case it is needed when new trials are added (e.g. if we add trials one-by-one). However, we should only do this when the search has not ended, as otherwise we keep an extra actor until the end of the experiment, wasting resources. This leads the tune_scale_up_down release test fail. In our refactor to #33045 we generalized object caching, but the eviction logic here explicitly keeps one object in cache. Our previous implementation in RayTrialExecutor relied on not calling the eviction function at all when trials were still coming up, essentially not adjusting the number of cached actors down. This is rarely a problem in practice, but does not make a clean contract when separated out into a component. In this PR, we change the logic as follows: When the search ended, no trials are pending execution, and we don't want to explicitly cache an actor, we force eviction of all cached objects. We are refactoring our execution backend, thus I believe it's sufficient to keep the release test to catch this regression. In the new backend we can add light weight unit tests to capture this behavior. Signed-off-by: Kai Fricke <kai@anyscale.com>
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests). By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected. Signed-off-by: Kai Fricke <coding@kaifricke.com> Signed-off-by: Kai Fricke <kai@anyscale.com>
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests). By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected. Signed-off-by: Kai Fricke <coding@kaifricke.com> Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: elliottower <elliot@elliottower.com>
…ject#33593) Similar regression that was originally fixed in ray-project#31974, but re-surfaced after ray-project#33045. With actor re-use, we speculatively keep one cached actor around in case it is needed when new trials are added (e.g. if we add trials one-by-one). However, we should only do this when the search has not ended, as otherwise we keep an extra actor until the end of the experiment, wasting resources. This leads the tune_scale_up_down release test fail. In our refactor to ray-project#33045 we generalized object caching, but the eviction logic here explicitly keeps one object in cache. Our previous implementation in RayTrialExecutor relied on not calling the eviction function at all when trials were still coming up, essentially not adjusting the number of cached actors down. This is rarely a problem in practice, but does not make a clean contract when separated out into a component. In this PR, we change the logic as follows: When the search ended, no trials are pending execution, and we don't want to explicitly cache an actor, we force eviction of all cached objects. We are refactoring our execution backend, thus I believe it's sufficient to keep the release test to catch this regression. In the new backend we can add light weight unit tests to capture this behavior. Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: elliottower <elliot@elliottower.com>
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests). By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected. Signed-off-by: Kai Fricke <coding@kaifricke.com> Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: Jack He <jackhe2345@gmail.com>
…ject#33593) Similar regression that was originally fixed in ray-project#31974, but re-surfaced after ray-project#33045. With actor re-use, we speculatively keep one cached actor around in case it is needed when new trials are added (e.g. if we add trials one-by-one). However, we should only do this when the search has not ended, as otherwise we keep an extra actor until the end of the experiment, wasting resources. This leads the tune_scale_up_down release test fail. In our refactor to ray-project#33045 we generalized object caching, but the eviction logic here explicitly keeps one object in cache. Our previous implementation in RayTrialExecutor relied on not calling the eviction function at all when trials were still coming up, essentially not adjusting the number of cached actors down. This is rarely a problem in practice, but does not make a clean contract when separated out into a component. In this PR, we change the logic as follows: When the search ended, no trials are pending execution, and we don't want to explicitly cache an actor, we force eviction of all cached objects. We are refactoring our execution backend, thus I believe it's sufficient to keep the release test to catch this regression. In the new backend we can add light weight unit tests to capture this behavior. Signed-off-by: Kai Fricke <kai@anyscale.com> Signed-off-by: Jack He <jackhe2345@gmail.com>
Why are these changes needed?
Actor reuse is currently implemented within the RayTrialExecutor and tightly coupled to its concepts. To simplify the code, this PR introduces a new internal _ObjectCache class that generically caches objects (e.g. Actors+PGs) given a grouping key (e.g. resource requests).
By moving the caching logic into a separate component, we can write better unit tests to ensure actor reuse works correctly and as expected.
Related issue number
Checks
git commit -s) in this PR.scripts/format.shto lint the changes in this PR.