Add retry mechanism and dynamic model loading to SONIC framework#27
Add retry mechanism and dynamic model loading to SONIC framework#27kakwok wants to merge 5 commits into
Conversation
…olve cmsTriton conflict in CMSSW_17_0_0_pre2. Co-authored-by: Trevin Lee <trl008@ucsd.edu>
0ea0d7a to
36ca055
Compare
| auto retryAction = RetryActionFactory::get()->create(actionType, retryPSet, this); | ||
| if (retryAction) { | ||
| //Convert to RetryActionPtr Type from raw pointer of retryAction | ||
| retryActions_.emplace_back(RetryActionPtr(retryAction.release())); |
There was a problem hiding this comment.
is the explicit RetryActionPtr() needed here? usually for emplace_back(), it shouldn't be
There was a problem hiding this comment.
Yes, because I think the RetryAction needs a custom deleter here, which is needed because it's a friend class of the SonicClient.
https://github.com/kakwok/cmssw/blob/SonicRetryDML_CMSSW_17_0_0_pre2/HeterogeneousCore/SonicCore/interface/SonicClientBase.h#L63-L69
Here's some more details from Claude:
RetryActionFactory::create() returns a std::unique_ptr<RetryActionBase> using the default deleter (std::default_delete<RetryActionBase>), since that's what edmplugin::PluginFactory hands back.
But retryActions_ stores your custom
RetryActionPtr = std::unique_ptr<RetryActionBase, RetryDeleter> — a different type, because RetryDeleter is a distinct functor from std::default_delete<RetryActionBase>.
| <test name="TestHeterogeneousCoreSonicTritonRetryActionSame" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/SonicTriton/test/tritonTest_cfg.py --modules TritonGraphProducer --maxEvents 2 --unittest --device cpu --retryAction same"/> | ||
| <test name="TestHeterogeneousCoreSonicTritonRetryActionDiff" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/SonicTriton/test/tritonTest_cfg.py --modules TritonGraphProducer --maxEvents 2 --unittest --device cpu --retryAction diff"/> |
There was a problem hiding this comment.
do these tests work without a driver script to enable/disable servers?
There was a problem hiding this comment.
They will pass but they does not do what they suggest to test.
The retryDiff test will require some fiddling because the server choice is still undeterministic among remote servers.
I can commit a retry same script retry_action_same.sh for now.
|
We will also have to update the various reco/miniaod algorithm configuration files that currently set |
|
Configs are updated as well Update allowedTries config |
| action = cms.PSet( | ||
| retryType = cms.string('RetrySameServerAction'), | ||
| allowedTries = cms.untracked.uint32(options.tries)) | ||
| if options.retryAction != 'same': | ||
| action.retryType = cms.string('RetryActionDiffServer') | ||
|
|
||
| fallback = cms.PSet(retryType = cms.string('RetryFallbackServerAction')) | ||
| return dict( | ||
| compression = cms.untracked.string(options.compression), | ||
| useSharedMemory = cms.untracked.bool(not options.noShm), | ||
| timeout = cms.untracked.uint32(options.timeout), | ||
| timeoutUnit = cms.untracked.string(options.timeoutUnit), | ||
| allowedTries = cms.untracked.uint32(options.tries), | ||
| Retry = cms.VPSet(action,fallback) |
There was a problem hiding this comment.
@kpedro88 On the topic of configuration, should we add a RetryFallbackServerAction to all configurations as default?
PR description:
Introduces a pluggable retry mechanism for SONIC inference clients and dynamic
model loading/unloading on the Triton fallback server. This enables automatic
recovery when a remote Triton server becomes unavailable during event processing.
Retry mechanism (
SonicCore)RetryActionBase: Plugin factory base class for retry strategies, withretry(),start(),finish()interfaceRetrySameServerAction: Retries inference on the same server (configurableallowedTries)SonicClientBase::finish(): Drives retry loop — on retryable failure(
finish(false)), iterates through registered retry actions; on non-retryablefailure (
finish(false, eptr)), propagates exception directlyRetry with server failover (
SonicTriton)RetryActionDiffServer: On failure, queriesTritonService::getBestServer()for an alternative healthy remote server, calls
updateServer()+eval()toretry on the new server
RetryFallbackServerAction: Last-resort action — when all other retries areexhausted, lazily starts the fallback server (idempotent), dynamically loads the
model to the fallback server via
TritonClient::switchToFallback(), and retries locally. Fires at mostonce per inference call.
TritonServicemaintains per-server health stats(liveness, readiness, failure count, queue time) via
updateServerHealth(),used by
getBestServer()to select the best candidateresolveServerName()prefers remote (non-fallback)servers when multiple servers provide the same model;
getBestServer()excludesfallback servers from candidate pool
Async retry redesign (holder-based)
evaluate()(Async mode) creates an innerWaitingTaskWithArenaHolderperinference attempt — the gRPC callback calls
doneWaiting()and returnsimmediately;
finish()/retry()/updateServer()are scheduled as TBB tasksDynamic model loading (
TritonService)loadModel()/unloadModel()with reference counting for the fallback serverstartFallbackServer()is idempotent; only started atpreBeginJobforunassigned models (no remote server available)
serversHealth_Configuration
RetryVPSet in client config(
retryType,allowedTries)customize.pyupdated with retry options, defaulted to addRetryFallbackServerActionas the last action.PR validation:
retry_diffServer_fallback.log