| 444 | } |
| 445 | |
| 446 | void ForEachOpGraphNecessaryCtrlEdge( |
| 447 | const OpGraph* op_graph, const std::function<void(const OpNode*, const OpNode*)>& Handler) { |
| 448 | auto IsOpGraphDataReachable = op_graph->CreatePredicatorIsReachable(); |
| 449 | op_graph->ForEachNode([&](OpNode* dst) { |
| 450 | for (const auto& ctrl_in_op_name : dst->op().op_conf().ctrl_in_op_name()) { |
| 451 | const OpNode* src = op_graph->OpNode4OpName(ctrl_in_op_name); |
| 452 | CHECK(!IsOpGraphDataReachable(dst, src)); |
| 453 | // src has ctrl to dst, but src has no data path to dst. |
| 454 | if (!IsOpGraphDataReachable(src, dst)) { |
| 455 | CHECK_EQ(dst->parallel_desc().parallel_num(), src->parallel_desc().parallel_num()); |
| 456 | const Shape* src_time_shape = CHECK_JUST(src->op().GetOpTimeShape()).get(); |
| 457 | const Shape* dst_time_shape = CHECK_JUST(dst->op().GetInputBlobFastestTimeShape()).get(); |
| 458 | if (dst_time_shape == nullptr) { |
| 459 | dst_time_shape = CHECK_JUST(dst->op().GetOpTimeShape()).get(); |
| 460 | } |
| 461 | if (src_time_shape->elem_cnt() != dst_time_shape->elem_cnt()) { |
| 462 | // NOTE(chengcheng): acc / pack op node can be merged and add ctrl edge. |
| 463 | CHECK(src->op().op_conf().has_user_conf()); |
| 464 | const std::string& op_type_name = src->op().op_conf().user_conf().op_type_name(); |
| 465 | CHECK(op_type_name == "acc" || op_type_name == "pack"); |
| 466 | const Shape* src_input_time_shape = |
| 467 | CHECK_JUST(src->op().GetInputBlobFastestTimeShape()).get(); |
| 468 | CHECK_EQ(src_input_time_shape->elem_cnt(), dst_time_shape->elem_cnt()); |
| 469 | } else { |
| 470 | CHECK_EQ(src_time_shape->elem_cnt(), dst_time_shape->elem_cnt()); |
| 471 | } |
| 472 | if (!src->parallel_desc().EqualsIgnoringHierarchy(dst->parallel_desc())) { |
| 473 | LOG(WARNING) << " Warning, there is a ctrl edge connected across placement from: " |
| 474 | << src->op().op_name() << " [" |
| 475 | << src->parallel_desc().parallel_conf().DebugString() |
| 476 | << "] to: " << dst->op().op_name() << " [" |
| 477 | << dst->parallel_desc().parallel_conf().DebugString() << "]"; |
| 478 | } |
| 479 | Handler(src, dst); |
| 480 | } |
| 481 | } |
| 482 | }); |
| 483 | } |
| 484 | |
| 485 | void GetHostInputLbis4OpNode(const OpNode* op_node, |
| 486 | std::vector<LogicalBlobId>* host_mem_input_lbis) { |
no test coverage detected