}
void AclCppOpGenerator::visit(ops::ConcatOp& op) {
- static const char* axis_names[] = {"arm_compute::DataLayoutDimension::HEIGHT",
+ static const char* axis_names[] = {"arm_compute::DataLayoutDimension::BATCHES",
+ "arm_compute::DataLayoutDimension::HEIGHT",
"arm_compute::DataLayoutDimension::WIDTH",
"arm_compute::DataLayoutDimension::CHANNEL"};
int axis = op.getAxis() < 0 ? op.getOutputShape(0).rank() + op.getAxis() : op.getAxis();
assert(axis < sizeof(axis_names) / sizeof(const char*));
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ auto out = genTensor(op, transposeShape<2, 1, 3, 0>(op.getOutputShape(0)));
auto prefix = out->name() + "_concatenate_layer";
auto inputs_var = _constrBlock->var("std::vector<arm_compute::ICLTensor*>", prefix + "_inputs");
auto inputs = inputs_var->use();
genPadStrideInfo(const Oper& op, const string& prefix, ArtifactBlock* block) {
using AF = ArtifactFactory;
- const Shape& strides = transposeShape<1, 0>(op.getStrides());
+ const Shape& strides = transposeShape<1, 0, 2>(op.getStrides());
assert(strides.rank() == 3 && strides.dim(2) == 1);
// array of paddings
pooling_type = "arm_compute::PoolingType::AVG";
break;
default:
- assert(false && "Not a supported pooling type");
+ throw AclCppException("Unsupported pooling type");
}
auto& prev_nodes = op.getPrevNodes();
auto in_op = prev_nodes[0].op;
auto in = AF::id(tensorName(in_op));
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ auto out = genTensor(op, transposeShape<2, 1, 3, 0>(op.getOutputShape(0)));
auto prefix = out->name() + "_pooling_layer";
auto pad_stride_info_var = genPadStrideInfo(op, prefix, _constrBlock);
auto in = AF::id(tensorName(in_op));
// Create the output tensor in the DOM.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ const Shape& out_shape = op.getOutputShape(0);
+ if (out_shape.rank() != 2)
+ throw AclCppException("Unsupported number of dimensions in fc layer");
+ auto out = genTensor(op, transposeShape<1, 0>(out_shape));
string operation_name = out->name() + "_fully_connected_layer";
// Create the weights tensor in the DOM and use its id.
auto in = AF::id(tensorName(in_op));
// Create the output tensor in the DOM and obtain its identifier.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ const Shape& out_shape = op.getOutputShape(0);
+ Shape transposed_shape;
+ switch (out_shape.rank()) {
+ case 4:
+ transposed_shape = transposeShape<2, 1, 3, 0>(out_shape);
+ break;
+ case 2:
+ transposed_shape = transposeShape<1, 0>(out_shape);
+ break;
+ case 1:
+ transposed_shape = out_shape;
+ break;
+ default:
+ throw AclCppException("Unsupported number of dimensions: " + to_string(out_shape.rank()));
+ }
+ shared_ptr<ArtifactId> out = genTensor(op, transposed_shape);
// Prefix used for the name of variables related to the operation implementation.
string operation_name = out->name() + "_bias_add_layer";
ir_biases_shape = transposeShape<1, 0>(op.getInputShape(0));
} else {
// ACL CLArithmeticAddition supports input tensors broadcasting.
- for (int i = 0; i < ir_input_shape.rank() - 1; ++i)
+ for (int i = 0; i < ir_input_shape.rank(); ++i)
ir_biases_shape.dim(i) = 1;
- ir_biases_shape.dim(-1) = ir_biases.getShape().dim(0);
+ ir_biases_shape.dim(2) = ir_biases.getShape().dim(0);
}
auto biases = genTensor(operation_name + "_biases", ir_biases_shape);
}
void AclCppOpGenerator::visit(ops::VariableOp& op) {
- auto tensor = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ auto tensor = genTensor(op, transposeShape<2, 1, 3, 0>(op.getOutputShape(0)));
allocate(tensor);
}
auto in = AF::id(tensorName(in_op));
// Create the output tensor in the DOM and return its id.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ const Shape& out_shape = op.getOutputShape(0);
+
+ // This check confirms that we can "safely" reshape data
+ // The only safe configuration of output shape is (1...1, N, 1 ... 1)
+ bool found_non_one = false;
+ for (int32_t i = 0; i < out_shape.rank(); ++i) {
+ if (out_shape.dim(i) != 1) {
+ if (found_non_one)
+ throw AclCppException("Unsupported result of reshape");
+ found_non_one = true;
+ }
+ }
+
+ Shape transposed_shape;
+ switch (out_shape.rank()) {
+ case 2:
+ transposed_shape = transposeShape<1, 0>(out_shape);
+ break;
+ case 1:
+ transposed_shape = out_shape;
+ break;
+ default:
+ throw AclCppException("Unsupported number of dimensions: " + to_string(out_shape.rank()));
+ }
+ shared_ptr<ArtifactId> out = genTensor(op, transposed_shape);
// Create an instance of the CLReshapeLayer class as a member of the artifact class.
auto layer = genLayer("arm_compute::CLReshapeLayer", out->name() + "_reshape_layer",
// Get input tensor identifier in the generated artifact.
auto in = AF::id(tensorName(in_op));
- // Generate output tensor description in the DOM.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ // Create the output tensor in the DOM and obtain its identifier.
+ const Shape& out_shape = op.getOutputShape(0);
+ Shape transposed_shape;
+ switch (out_shape.rank()) {
+ case 4:
+ transposed_shape = transposeShape<2, 1, 3, 0>(out_shape);
+ break;
+ case 2:
+ transposed_shape = transposeShape<1, 0>(out_shape);
+ break;
+ case 1:
+ transposed_shape = out_shape;
+ break;
+ default:
+ throw AclCppException("Unsupported number of dimensions: " + to_string(out_shape.rank()));
+ }
+ shared_ptr<ArtifactId> out = genTensor(op, transposed_shape);
+
auto operation_name = out->name() + "_scale_layer";
const auto& ir_scales = op.getWeights();
// Reshape the IR scales tensor and generate the corresponding DOM tensor.
Shape ir_scales_shape;
- const auto ir_input_shape = transposeShape<1, 0, 2>(op.getInputShape(0));
+ const auto ir_input_shape = transposeShape<2, 1, 3, 0>(op.getInputShape(0));
ir_scales_shape.resize(ir_input_shape.rank());
// ACL CLArithmeticDivision supports input tensors broadcasting.
- for (int i = 0; i < ir_input_shape.rank() - 1; ++i)
+ for (int i = 0; i < ir_input_shape.rank(); ++i)
ir_scales_shape.dim(i) = 1;
- ir_scales_shape.dim(-1) = ir_scales.getShape().dim(0);
+ ir_scales_shape.dim(2) = ir_scales.getShape().dim(0);
auto scales = genTensor(operation_name + "_scales", ir_scales_shape);
// We do not use the genMultiplication() function here because the input needs broadcasting.
auto in = AF::id(tensorName(in_op));
// Create the output tensor in the DOM.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ auto out = genTensor(op, transposeShape<2, 1, 3, 0>(op.getOutputShape(0)));
string operation_name = out->name() + suffix;
// Generate a tensor for weights (kernel) in the DOM.
auto in = AF::id(tensorName(in_op));
// Create the output tensor in the DOM and return its id.
- auto out = genTensor(op, transposeShape<1, 0, 2>(op.getOutputShape(0)));
+ auto out = genTensor(op, transposeShape<2, 1, 3, 0>(op.getOutputShape(0)));
auto prefix = out->name() + "_activation_layer";
// Create an instance of the ActivationLayerInfo class as a local variable in the artifact