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 7 commits into
Conversation
…olve cmsTriton conflict in CMSSW_17_0_0_pre2. Co-authored-by: Trevin Lee <trl008@ucsd.edu>
0ea0d7a to
36ca055
Compare
| <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.
There was a problem hiding this comment.
I think we really need the RetryActionDiff test as a unit test if we're going to claim that functionality works. For now, maybe we can come up with some arbitrary but deterministic way to do the server choice. Alternatively, could try to have the test script parse the CMSSW output and figure out which server was chosen, in order to kill it and force the retry...
There was a problem hiding this comment.
done in kakwok@c9b55a1
Server is stored with std::set<std::string>, which is sorted lexicographically.
Note that the server name from the tritonTest_cfg command in the test script is used to pick the server, not the initial server names from cmsTriton.
The script tests the following situation:
- Having two remote servers
server1,server2and starting the fallback server. - picks
server1 - script kills
server1, client continues withserver2 - script kills
server2, client continues with fallback server.
We can add other test scenarios if desired.
|
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?
There was a problem hiding this comment.
Probably. We may be able to do that by modifying https://github.com/cms-sw/cmssw/blob/b8fdcd5f6d1e240d3966e67d062d3880c2a33eea/HeterogeneousCore/SonicTriton/src/TritonClient.cc#L586
rather than having to make more modifications to a growing list of algorithm-specific config files...
| def getOptions(parser, verbose=False): | ||
| options = parser.parse_args() |
| @@ -126,6 +131,6 @@ void MyClient::fillPSetDescription(edm::ParameterSetDescription& iDesc) { | |||
|
|
|||
| As indicated, the `fillBasePSetDescription()` function should always be applied to the `descClient` object, | |||
| to ensure that it includes the necessary parameters. | |||
| (Calling `fillBasePSetDescription(descClient, false)` will omit the `allowedTries` parameter, disabling retries.) | |||
| (Calling `fillBasePSetDescription(descClient, false)` will omit the `Retry` parameter, disabling retries.) | |||
There was a problem hiding this comment.
I'm not sure this behavior is still desirable. Since Retry is a vector, it could just always exist, but be an empty vector if retries are disabled.
| //enforce sync mode for fallback CPU server to avoid contention | ||
| if (serverType_ == TritonServerType::LocalCPU) | ||
| setMode(SonicMode::Sync); | ||
| if (serverType_ == TritonServerType::Remote) |
There was a problem hiding this comment.
this should be else (async is also desired for LocalGPU)
however, this then overrides the user setting in all cases, making the mode Python parameter pointless. ideally, we should have some default value and only override to Async if the default is not provided. (Sync should always be used for LocalCPU, even if the user provides a different value.)
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