| 142 | } |
| 143 | |
| 144 | Status SingleMachine::Run(const GraphDef& graph_def, |
| 145 | const std::vector<std::pair<string, Tensor>>& feed, |
| 146 | const std::vector<string>& fetch, |
| 147 | RunMetadata* metadata) { |
| 148 | mutex_lock l(this->last_graph_mu_); |
| 149 | if (last_graph_ != &graph_def) { |
| 150 | TF_RETURN_IF_ERROR(ResetSession()); |
| 151 | TF_RETURN_IF_ERROR(session_->Create(graph_def)); |
| 152 | if (!init_ops_.empty()) { |
| 153 | init_metadata_ = RunMetadata(); |
| 154 | int64 timeout_s = timeout_s_ + expected_init_time_s_; |
| 155 | TF_RETURN_IF_ERROR( |
| 156 | RunWithTimeout({}, init_ops_, &init_metadata_, timeout_s)); |
| 157 | // The compute cost for init ops is likely to be pessimistic since init |
| 158 | // ops are run only once before warmup. Therefore we only keep their |
| 159 | // memory costs. |
| 160 | for (auto node : *init_metadata_.mutable_cost_graph()->mutable_node()) { |
| 161 | node.clear_compute_cost(); |
| 162 | } |
| 163 | // Also clear the timeline to save memory |
| 164 | init_metadata_.clear_step_stats(); |
| 165 | } |
| 166 | // We can have at most one hardware trace. Use it for the main graph, and |
| 167 | // downgrade tracing of the queue runners to a software trace. |
| 168 | RunOptions queue_options = run_options_; |
| 169 | if (queue_options.trace_level() >= RunOptions::HARDWARE_TRACE) { |
| 170 | queue_options.set_trace_level(RunOptions::SOFTWARE_TRACE); |
| 171 | } |
| 172 | for (size_t i = 0; i < queue_runner_defs_.size(); ++i) { |
| 173 | std::unique_ptr<QueueRunner> queue_runner; |
| 174 | TF_RETURN_IF_ERROR(QueueRunner::New(queue_runner_defs_[i], |
| 175 | coordinator_.get(), &queue_runner)); |
| 176 | |
| 177 | TF_RETURN_IF_ERROR(queue_runner->StartAndCollectCostGraph(session_.get(), |
| 178 | queue_options)); |
| 179 | TF_RETURN_IF_ERROR(coordinator_->RegisterRunner(std::move(queue_runner))); |
| 180 | TF_RETURN_IF_ERROR(coordinator_->GetStatus()); |
| 181 | } |
| 182 | |
| 183 | // Warmup TensorFlow if needed |
| 184 | for (int i = 0; i < NumWarmupSteps(); ++i) { |
| 185 | TF_RETURN_IF_ERROR(RunWithTimeout(feed, fetch, nullptr)); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | if (metadata) { |
| 190 | TF_RETURN_IF_ERROR(RunWithTimeout(feed, fetch, metadata)); |
| 191 | // Merge the costs of the initialization and the queue runners. |
| 192 | CostGraphDef queue_costs; |
| 193 | TF_RETURN_IF_ERROR(coordinator_->ExportCostGraph(&queue_costs)); |
| 194 | MergeCosts(metadata->mutable_cost_graph(), init_metadata_.cost_graph(), |
| 195 | queue_costs); |
| 196 | } else { |
| 197 | TF_RETURN_IF_ERROR(RunWithTimeout(feed, fetch, nullptr)); |
| 198 | } |
| 199 | |
| 200 | last_graph_ = &graph_def; |
| 201 | |