| 268 | } // namespace dicefusion |
| 269 | |
| 270 | Status DiceFusion::Optimize(Cluster* cluster, const GrapplerItem& item, |
| 271 | GraphDef* output) { |
| 272 | *output = item.graph; |
| 273 | #if defined(__GNUC__) && (__GNUC__ > 6) && (__AVX512F__) |
| 274 | Status status; |
| 275 | utils::MutableGraphView graph_view(output, &status); |
| 276 | TF_RETURN_IF_ERROR(status); |
| 277 | TF_RETURN_IF_ERROR(graph_view.SortTopologically(/*ignore_cycles=*/false, {})); |
| 278 | const int num_nodes = item.graph.node_size(); |
| 279 | // invalidated_nodes - nodes that have been changed into a fused op |
| 280 | // nodes_to_delete - nodes that were fused into a fused op and are not needed |
| 281 | // anymore |
| 282 | std::vector<bool> invalidated_nodes(num_nodes); |
| 283 | std::vector<bool> nodes_to_delete(num_nodes); |
| 284 | const GraphDef* graph = graph_view.graph(); |
| 285 | |
| 286 | VLOG(3) << "Before Dice fusion rewrites: " << graph->DebugString(); |
| 287 | |
| 288 | for (int i = 0; i < num_nodes; ++i) { |
| 289 | if (invalidated_nodes[i] || nodes_to_delete[i]) continue; |
| 290 | |
| 291 | dicefusion::DicePattern base; |
| 292 | if (dicefusion::FindDicePattern(graph_view, i, &base)) { |
| 293 | const auto& fused_node = graph->node(i); |
| 294 | VLOG(2) << "Optimizing fused dice node " << SummarizeNodeDef(fused_node); |
| 295 | |
| 296 | std::vector<int> dead_nodes = { |
| 297 | base.sub_1_id, base.sub_2_id, base.sigmoid_id, base.mul_1_id, |
| 298 | base.mul_2_id, base.mul_3_id, base.mul_4_id, base.sub_2_input_id}; |
| 299 | for (auto& id : dead_nodes) nodes_to_delete[id] = true; |
| 300 | invalidated_nodes[base.add_id] = true; |
| 301 | |
| 302 | // Adding fused dice op |
| 303 | const NodeDef& add = graph->node(base.add_id); |
| 304 | |
| 305 | NodeDef dice_op; |
| 306 | dice_op.set_name(add.name()); |
| 307 | dice_op.set_op("Dice"); |
| 308 | dice_op.set_device(add.device()); |
| 309 | |
| 310 | // Get input |
| 311 | std::vector<int> nodes_with_inputs = {base.mul_4_id, base.sub_1_id, |
| 312 | base.mul_1_id, base.mul_3_id}; |
| 313 | std::set<std::string> names; |
| 314 | for (int i = 0; i < dead_nodes.size(); ++i) { |
| 315 | const auto* node_view = graph_view.GetNode(dead_nodes.at(i)); |
| 316 | const auto* node_def = node_view->node(); |
| 317 | names.insert(node_def->name()); |
| 318 | } |
| 319 | std::set<std::string> added_input; |
| 320 | for (int i = 0; i < nodes_with_inputs.size(); ++i) { |
| 321 | const int id = nodes_with_inputs.at(i); |
| 322 | const auto* node_view = graph_view.GetNode(id); |
| 323 | const auto* node_def = node_view->node(); |
| 324 | const std::size_t num_inputs = node_view->NumRegularFanins(); |
| 325 | for (size_t j = 0; j < num_inputs; ++j) { |
| 326 | std::string node_name = |
| 327 | dicefusion::get_node_by_tensor(node_def->input(j)); |
nothing calls this directly
no test coverage detected