| 478 | } |
| 479 | |
| 480 | void ProcessFuncBatch(std::unique_ptr<Batch> batch) const { |
| 481 | if (batch->empty()) { |
| 482 | return; |
| 483 | } |
| 484 | |
| 485 | // We use the 'propagated_context' from one of the threads which setup one |
| 486 | // of the tasks. This will propagate any common context over all the threads |
| 487 | // which are running this Session, of which this BatchOp is a part. |
| 488 | WithContext wc(batch->task(batch->num_tasks() - 1).propagated_context); |
| 489 | |
| 490 | OpKernelContext* last_task_context = |
| 491 | batch->task(batch->num_tasks() - 1).context; |
| 492 | |
| 493 | // Regardless of the outcome, we need to propagate the status to the |
| 494 | // individual tasks and signal that they are done. We use MakeCleanup() to |
| 495 | // ensure that this happens no matter how we exit the method below. |
| 496 | Status status; |
| 497 | bool cleanup_done = false; |
| 498 | auto cleanup_fn = [&cleanup_done, &batch](const Status& status) { |
| 499 | if (cleanup_done) { |
| 500 | return; |
| 501 | } |
| 502 | for (int i = 0; i < batch->num_tasks(); ++i) { |
| 503 | batch->mutable_task(i)->context->SetStatus(status); |
| 504 | batch->mutable_task(i)->done_callback(); |
| 505 | } |
| 506 | cleanup_done = true; |
| 507 | }; |
| 508 | auto finally = |
| 509 | gtl::MakeCleanup([&cleanup_fn, &status] { cleanup_fn(status); }); |
| 510 | |
| 511 | status = ValidateBatch(*batch); |
| 512 | if (!status.ok()) { |
| 513 | return; |
| 514 | } |
| 515 | |
| 516 | std::vector<Tensor> concatenated_tensors; |
| 517 | status = |
| 518 | ConcatInputTensors(*batch, last_task_context, &concatenated_tensors); |
| 519 | if (!status.ok()) { |
| 520 | return; |
| 521 | } |
| 522 | FunctionLibraryRuntime::Options opts; |
| 523 | opts.step_container = last_task_context->step_container(); |
| 524 | opts.cancellation_manager = last_task_context->cancellation_manager(); |
| 525 | opts.stats_collector = last_task_context->stats_collector(); |
| 526 | opts.rendezvous = last_task_context->rendezvous(); |
| 527 | opts.runner = last_task_context->runner(); |
| 528 | |
| 529 | auto* flib = last_task_context->function_library(); |
| 530 | std::vector<Tensor> combined_outputs; |
| 531 | Notification done; |
| 532 | std::vector<Tensor> args(concatenated_tensors.begin(), |
| 533 | concatenated_tensors.end()); |
| 534 | const auto& captured_inputs = |
| 535 | batch->task(batch->num_tasks() - 1).captured_inputs; |
| 536 | args.insert(args.end(), captured_inputs.begin(), captured_inputs.end()); |
| 537 |
nothing calls this directly
no test coverage detected