MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / AddExtraOutputs

Function AddExtraOutputs

tensorflow/lite/toco/import_tensorflow.cc:2148–2199  ·  view source on GitHub ↗

In TensorFlow GraphDef, when a node has multiple outputs, they are named name:0, name:1, ... where 'name' is the node's name(). Just 'name' is an equivalent shorthand form for name:0. A TensorFlow GraphDef does not explicitly list all the outputs of each node (unlike inputs), it being implied by the node's name and operator type (the latter implies the number of outputs). This makes it non-trivial

Source from the content-addressed store, hash-verified

2146// at least each node lists explicitly its inputs, so after we've loaded
2147// all nodes, we can use that information.
2148void AddExtraOutputs(Model* model) {
2149 // Construct the list of all arrays consumed by anything in the graph.
2150 std::vector<string> consumed_arrays;
2151 // Add arrays consumed by an op.
2152 for (const auto& consumer_op : model->operators) {
2153 for (const string& input : consumer_op->inputs) {
2154 consumed_arrays.push_back(input);
2155 }
2156 }
2157 // Add global outputs of the model.
2158 for (const string& output_array : model->flags.output_arrays()) {
2159 consumed_arrays.push_back(output_array);
2160 }
2161 // Add arrays consumed by a RNN back-edge.
2162 for (const auto& rnn_state : model->flags.rnn_states()) {
2163 consumed_arrays.push_back(rnn_state.back_edge_source_array());
2164 }
2165 // Now add operator outputs so that all arrays that are consumed,
2166 // are produced.
2167 for (const string& consumed_array : consumed_arrays) {
2168 // Test if consumed_array is already the output of some op.
2169 // This has occurred in a model where separate nodes had names of the form
2170 // foo:$i with the same base name foo.
2171 if (GetOpWithOutput(*model, consumed_array)) {
2172 continue;
2173 }
2174 // Split the consumed array name into the form name:output_index.
2175 const std::vector<string>& split = absl::StrSplit(consumed_array, ':');
2176 // If not of the form name:output_index, then this is not an additional
2177 // output of a node with multiple outputs, so nothing to do here.
2178 if (split.size() != 2) {
2179 continue;
2180 }
2181 int output_index = 0;
2182 if (!absl::SimpleAtoi(split[1], &output_index)) {
2183 continue;
2184 }
2185 // Each op is initially recorded as producing at least the array that
2186 // has its name. We use that to identify the producer node.
2187 auto* producer_op = GetOpWithOutput(*model, split[0]);
2188 if (!producer_op) {
2189 continue;
2190 }
2191 // Add extra outputs to that producer node, all the way to the
2192 // output_index.
2193 while (producer_op->outputs.size() <= output_index) {
2194 using toco::port::StringF;
2195 producer_op->outputs.push_back(
2196 StringF("%s:%d", split[0], producer_op->outputs.size()));
2197 }
2198 }
2199}
2200
2201bool InlineAllFunctions(GraphDef* graphdef) {
2202 if (graphdef->library().function().empty()) {

Callers 1

ImportTensorFlowGraphDefFunction · 0.85

Calls 4

GetOpWithOutputFunction · 0.85
StringFFunction · 0.85
push_backMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected