| 121 | } |
| 122 | |
| 123 | Status CloneConstantsForBetterClusteringPass::Run( |
| 124 | const GraphOptimizationPassOptions& options) { |
| 125 | if (GetGlobalJitLevelForGraph(options) == OptimizerOptions::OFF) { |
| 126 | return Status::OK(); |
| 127 | } |
| 128 | |
| 129 | Graph* g = options.graph->get(); |
| 130 | absl::flat_hash_set<string> name_set; |
| 131 | absl::c_transform(g->nodes(), std::inserter(name_set, name_set.begin()), |
| 132 | [](Node* n) { return n->name(); }); |
| 133 | std::vector<Node*> nodes; |
| 134 | for (Node* n : g->nodes()) { |
| 135 | // We rely on the immutability of Tensors to safely clone Const operations. |
| 136 | // However, "in place" ops do not respect the immutability of Tensors so we |
| 137 | // avoid this transformation when such ops are present in the graph. |
| 138 | // |
| 139 | // In-place operations are problematic because they break the semantic |
| 140 | // illusion that tensorflow::Tensor instances are immutable. For instance |
| 141 | // if we have the following graph: |
| 142 | // |
| 143 | // digraph { |
| 144 | // SRC -> Const |
| 145 | // SRC -> I |
| 146 | // SRC -> V |
| 147 | // Const -> Identity |
| 148 | // Const -> InplaceAdd [label="x"] |
| 149 | // I -> InplaceAdd [label="i"] |
| 150 | // V -> InplaceAdd [label="v"] |
| 151 | // InplaceAdd -> Identity [style=dotted] |
| 152 | // } |
| 153 | // |
| 154 | // then the value produced by `Identity` is Const+I*V since InplaceAdd |
| 155 | // modifies the tensor in place. However, if we clone `Const` and turn the |
| 156 | // graph into: |
| 157 | // |
| 158 | // digraph { |
| 159 | // SRC -> "Const/clone_1" |
| 160 | // SRC -> "Const/clone_2" |
| 161 | // SRC -> I |
| 162 | // SRC -> V |
| 163 | // "Const/clone_1" -> Identity |
| 164 | // "Const/clone_2" -> InplaceAdd [label="x"] |
| 165 | // I -> InplaceAdd [label="i"] |
| 166 | // V -> InplaceAdd [label="v"] |
| 167 | // InplaceAdd -> Identity [style=dotted] |
| 168 | // } |
| 169 | // |
| 170 | // then `Identity` no longer produces Const+I*V because the InplaceAdd |
| 171 | // operation only modifies Const/clone_2 in place. |
| 172 | |
| 173 | if (IsInPlaceOp(n->type_string())) { |
| 174 | return Status::OK(); |
| 175 | } |
| 176 | nodes.push_back(n); |
| 177 | } |
| 178 | |
| 179 | // Iterate over a copy of the nodes to avoid iterating over g->nodes() while |
| 180 | // creating more nodes. |
nothing calls this directly
no test coverage detected