| 391 | } // namespace |
| 392 | |
| 393 | void TFCode::AddNode(TFGraphNode* node) { |
| 394 | if (!node->call_stack() || node->call_stack()->traces().empty()) { |
| 395 | return; |
| 396 | } |
| 397 | // We infer the forward operation name from gradient op name. So, we can |
| 398 | // map gradient op traces to forward op traces. |
| 399 | // E.g. gradient node of 'inp_1/Conv2D' would be 'gradients/inp_1/Conv2D_grad. |
| 400 | string forward_name; |
| 401 | if (IsGradNode(node->name(), &forward_name)) { |
| 402 | auto grad_nodes_it = grad_nodes_.find(forward_name); |
| 403 | if (grad_nodes_it != grad_nodes_.end()) { |
| 404 | grad_nodes_it->second.push_back(node); |
| 405 | } else { |
| 406 | grad_nodes_.insert( |
| 407 | std::pair<string, std::vector<TFGraphNode*>>(forward_name, {node})); |
| 408 | } |
| 409 | return; |
| 410 | } else { |
| 411 | forward_nodes_[node->name()] = node; |
| 412 | } |
| 413 | |
| 414 | if (!root_) { |
| 415 | graph_root_.reset(new TFMultiGraphNode(kTFProfRoot)); |
| 416 | root_.reset(new CodeNode(graph_root_.get(), nullptr, "")); |
| 417 | } |
| 418 | |
| 419 | CodeNode* pre_code_node = root_.get(); |
| 420 | // TODO(xpan): Consider to release CodeDef after TFCode is built. It |
| 421 | // takes a lot of memory. |
| 422 | std::set<string> traces; |
| 423 | for (int i = 0; i < node->call_stack()->traces().size(); ++i) { |
| 424 | // Unlike op name, which is globally unique, trace name is only unique |
| 425 | // w.r.t. it's parent. |
| 426 | const string& trace = GetTraceString(node->call_stack()->traces().at(i)); |
| 427 | traces.insert(trace); |
| 428 | pre_code_node = pre_code_node->AddChildren( |
| 429 | trace, &node->call_stack()->traces().at(i), ""); |
| 430 | if (i == node->call_stack()->traces().size() - 1) { |
| 431 | pre_code_node->node->AddGraphNode(node); |
| 432 | } |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | void TFCode::Build() { |
| 437 | int64 unaccounted_nodes = 0; |
nothing calls this directly
no test coverage detected