| 218 | } |
| 219 | |
| 220 | void BaseCollectiveExecutor::ExecuteAsync(OpKernelContext* ctx, |
| 221 | const CollectiveParams& col_params, |
| 222 | const string& exec_key, |
| 223 | StatusCallback done) { |
| 224 | // On any individual collective Op failure we need to abort the |
| 225 | // BufRendezvous so that other Ops in the instance don't hang |
| 226 | // waiting for transmissions that will never happen. Do so after a |
| 227 | // delay so that the original error status is more likely to |
| 228 | // propagate up, and peers are unlikely to re-create the purged |
| 229 | // BufRendezvous by late-arriving requests. |
| 230 | StatusCallback done_safe = [this, done](const Status& s) { |
| 231 | if (!s.ok()) { |
| 232 | Ref(); // Ensure this lasts until the closure executes. |
| 233 | SchedNonBlockingClosureAfter(1000000, [this, s] { |
| 234 | remote_access_->buf_rendezvous()->StartAbort(s); |
| 235 | Unref(); |
| 236 | }); |
| 237 | } |
| 238 | done(s); |
| 239 | }; |
| 240 | |
| 241 | Tensor* output = ctx->mutable_output(0); |
| 242 | const Tensor* input = (col_params.instance.type == REDUCTION_COLLECTIVE || |
| 243 | col_params.instance.type == GATHER_COLLECTIVE || |
| 244 | (col_params.instance.type == BROADCAST_COLLECTIVE && |
| 245 | col_params.is_source)) |
| 246 | ? &ctx->input(0) |
| 247 | : nullptr; |
| 248 | CollectiveImplementationInterface* col_impl = nullptr; |
| 249 | Status status = CreateCollective(col_params, &col_impl); |
| 250 | if (!status.ok()) { |
| 251 | done_safe(status); |
| 252 | DCHECK_EQ(nullptr, col_impl); |
| 253 | return; |
| 254 | } |
| 255 | CollectiveContext* col_ctx = |
| 256 | new CollectiveContext(this, dev_mgr_, ctx, CtxParams(ctx), col_params, |
| 257 | exec_key, step_id_, input, output); |
| 258 | status = col_impl->InitializeCollectiveContext(col_ctx); |
| 259 | if (!status.ok()) { |
| 260 | done_safe(status); |
| 261 | delete col_ctx; |
| 262 | delete col_impl; |
| 263 | return; |
| 264 | } |
| 265 | // Run on an unbounded work queue that can handle blocking work so as to not |
| 266 | // starve executor threads. |
| 267 | remote_access_->RunClosure([col_impl, col_ctx, done_safe, ctx]() { |
| 268 | profiler::TraceMe activity( |
| 269 | [&] { |
| 270 | return strings::StrCat(ctx->op_kernel().name(), ":", |
| 271 | ctx->op_kernel().type_string(), |
| 272 | "#id=", ctx->step_id(), "#"); |
| 273 | }, |
| 274 | profiler::TraceMeLevel::kInfo); |
| 275 | col_impl->Run([col_impl, col_ctx, done_safe](const Status& s) { |
| 276 | done_safe(s); |
| 277 | delete col_ctx; |
nothing calls this directly
no test coverage detected