| 83 | } |
| 84 | |
| 85 | void PartitionedCallOp::ComputeAsync(OpKernelContext* ctx, DoneCallback done) { |
| 86 | FunctionLibraryRuntime* lib = ctx->function_library(); |
| 87 | OP_REQUIRES_ASYNC(ctx, lib != nullptr, |
| 88 | errors::Internal("No function library is provided."), done); |
| 89 | |
| 90 | // The function body's graph is placed and partitioned the first time |
| 91 | // `ComputeAsync` is invoked; every subsequent invocation calls each |
| 92 | // of the function shards yielded by partitioning. |
| 93 | // |
| 94 | // The partitioning step yields a set of devices on which to run the |
| 95 | // function, and exactly one function shard is created for each device |
| 96 | // Inputs and outputs are pinned to the local device, for simplicity. |
| 97 | // |
| 98 | // TODO(akshayka): Support re-sharding the function on subsequent calls, |
| 99 | // via, e.g., virtual device annotations and a list of device names |
| 100 | // supplied through an attribute. |
| 101 | // |
| 102 | // TODO(akshayka): Add a fastpath for functions that execute on a single |
| 103 | // device. |
| 104 | FunctionLibraryRuntime::Handle handle; |
| 105 | // If we are instantiating the function, we can efficiently extract the |
| 106 | // inputs while instantiating. Else, we extract them separately below. |
| 107 | std::vector<Tensor> inputs; |
| 108 | bool inputs_extracted = false; |
| 109 | { |
| 110 | mutex_lock l(mu_); |
| 111 | auto it = handles_.find(lib); |
| 112 | if (it == handles_.end()) { |
| 113 | OP_REQUIRES_OK_ASYNC(ctx, Instantiate(lib, ctx, &inputs, &handle), done); |
| 114 | inputs_extracted = true; |
| 115 | handles_[lib] = handle; |
| 116 | } else { |
| 117 | handle = it->second; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | if (!inputs_extracted) { |
| 122 | OpInputList args; |
| 123 | OP_REQUIRES_OK_ASYNC(ctx, ctx->input_list("args", &args), done); |
| 124 | inputs.reserve(args.size()); |
| 125 | for (const Tensor& tensor : args) { |
| 126 | inputs.push_back(tensor); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | RunFunction(handle, inputs, lib, ctx, done); |
| 131 | } |
| 132 | |
| 133 | Status PartitionedCallOp::FillOutputDevices( |
| 134 | const FunctionLibraryRuntime& lib, const Device& cpu_device, |
nothing calls this directly
no test coverage detected