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

Method Run

tensorflow/lite/toco/graph_transformations/unroll_batch_matmul.cc:133–259  ·  view source on GitHub ↗

Unrolls a BatchMatMul on the batch dimension. We need to slice each batch out of the inputs, matmul them individually, then stack them all back together at the end.

Source from the content-addressed store, hash-verified

131// We need to slice each batch out of the inputs, matmul them individually, then
132// stack them all back together at the end.
133::tensorflow::Status UnrollBatchMatMul::Run(Model* model, std::size_t op_index,
134 bool* modified) {
135 *modified = false;
136 auto batch_op_it = model->operators.begin() + op_index;
137 if (batch_op_it->get()->type != OperatorType::kBatchMatMul) {
138 return ::tensorflow::Status::OK();
139 }
140 const auto* batch_op =
141 static_cast<const BatchMatMulOperator*>(batch_op_it->get());
142 auto& tail_it = batch_op_it;
143
144 string input_lhs = batch_op->inputs[0];
145 string input_rhs = batch_op->inputs[1];
146 const auto& input_lhs_array = model->GetArray(input_lhs);
147 const auto& input_rhs_array = model->GetArray(input_rhs);
148 if (!input_lhs_array.has_shape() || !input_rhs_array.has_shape())
149 return ::tensorflow::Status::OK();
150
151 // Transpose LHS input if necessary.
152 if (batch_op->adj_x) {
153 TransposeOperator* transpose_op = TransposeInput(input_lhs, model);
154 tail_it = model->operators.emplace(tail_it, transpose_op) + 1;
155 input_lhs = transpose_op->outputs[0];
156 }
157 const auto& input_array_a = model->GetArray(input_lhs);
158
159 // Transpose RHS input if necessary.
160 if (batch_op->adj_y) {
161 TransposeOperator* transpose_op = TransposeInput(input_rhs, model);
162 tail_it = model->operators.emplace(tail_it, transpose_op) + 1;
163 input_rhs = transpose_op->outputs[0];
164 }
165 const auto& input_array_b = model->GetArray(input_rhs);
166
167 // Ensure that input ranks are at least 2 and batch shapes are broadcastable.
168 const int dims_a = input_array_a.shape().dimensions_count();
169 const int dims_b = input_array_b.shape().dimensions_count();
170 CHECK_GE(dims_a, 2) << "First input must have rank >= 2";
171 CHECK_GE(dims_b, 2) << "Second input must have rank >= 2";
172
173 ::tensorflow::MatMulBCast bcast(
174 ToInlinedVector(input_array_a.shape().dims()),
175 ToInlinedVector(input_array_b.shape().dims()));
176 CHECK(bcast.IsValid()) << "Input batch dimensions must be broadcastable";
177
178 CHECK_EQ(input_array_a.shape().dims(dims_a - 1),
179 input_array_b.shape().dims(dims_b - 2))
180 << "Input dimensions must be compatible for multipication. shape a = ["
181 << absl::StrJoin(input_array_a.shape().dims(), ", ") << "], shape b = ["
182 << absl::StrJoin(input_array_b.shape().dims(), ", ") << "]";
183
184 if (dims_a == 2 && dims_b == 2) {
185 // This is really just a MatMul.
186 AddMessageF("Replacing non-batch BatchMatMul %s by a MatMul operator",
187 LogName(*batch_op));
188 auto* matmul_op = new TensorFlowMatMulOperator;
189 matmul_op->inputs = {input_lhs, input_rhs};
190 matmul_op->outputs = batch_op->outputs;

Callers

nothing calls this directly

Calls 15

TransposeInputFunction · 0.85
ToInlinedVectorFunction · 0.85
LogNameFunction · 0.85
DeleteOpAndArraysFunction · 0.85
SliceInputFunction · 0.85
AvailableArrayNameFunction · 0.85
CreateInt32ArrayFunction · 0.85
has_shapeMethod · 0.80
dimensions_countMethod · 0.80
output_batch_sizeMethod · 0.80
x_batch_sizeMethod · 0.80
y_batch_sizeMethod · 0.80

Tested by

no test coverage detected