Skip to content

Commit a0bf373

Browse files
authored
[onert/acl_cl] Refactor operation handling to use separate operation files (#16268)
This commit refactors ACL-CL backend to move operation implementations from KernelGenerator.cc and Validator.h to separate operation files in ops/ directory. This improves code organization and consistency with other backend patterns. ONE-DCO-1.0-Signed-off-by: Hyeongseok Oh <hseok82.oh@samsung.com>
1 parent 7da2f65 commit a0bf373

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2805
-1522
lines changed

runtime/onert/backend/acl_cl/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ file(GLOB SOURCES "*.cc")
1010
file(GLOB OPERAND_SOURCES "operand/*.cc")
1111
list(APPEND SOURCES ${OPERAND_SOURCES})
1212
macro(OP NAME)
13-
# ACL_CL backend doesn't have separate operation files,
14-
# but we include the macro for consistency with other backend pattern
13+
list(APPEND SOURCES ops/${NAME}.cc)
1514
endmacro(OP)
1615
include(Operation.lst)
1716

runtime/onert/backend/acl_cl/KernelGenerator.cc

Lines changed: 0 additions & 1504 deletions
Large diffs are not rendered by default.

runtime/onert/backend/acl_cl/Validator.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ class Validator : public backend::ValidatorBase
3030
Validator(const ir::Graph &graph) : backend::ValidatorBase(graph) {}
3131

3232
private:
33-
#define OP(InternalName) \
34-
void visit(const ir::operation::InternalName &) override { _supported = true; }
33+
#define OP(InternalName) void visit(const ir::operation::InternalName &) override;
3534
#include "Operation.lst"
3635
#undef OP
3736
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../KernelGenerator.h"
18+
#include "../Validator.h"
19+
20+
#include <AclKernelGen.h>
21+
22+
namespace onert::backend::acl_cl
23+
{
24+
25+
void Validator::visit(const ir::operation::ArgMinMax &) { _supported = true; }
26+
27+
void KernelGenerator::visit(const ir::operation::ArgMinMax &node)
28+
{
29+
const auto ofm_index{node.getOutputs().at(0)};
30+
const auto ifm_index{node.getInputs().at(ir::operation::ArgMinMax::Input::INPUT)};
31+
const auto axis_index{node.getInputs().at(ir::operation::ArgMinMax::Input::AXIS)};
32+
33+
auto ifm_shape = _ctx.at(ifm_index).shape();
34+
auto ofm_shape = _ctx.at(ofm_index).shape();
35+
36+
assert((ifm_shape.rank() - 1) == ofm_shape.rank());
37+
38+
auto ofm_tensor = _tensor_reg->getAclTensor(ofm_index);
39+
auto ifm_tensor = _tensor_reg->getAclTensor(ifm_index);
40+
const auto ifm_rank = _ctx.at(ifm_index).shape().rank();
41+
42+
int axis_value = _ctx.at(axis_index).asScalar<int32_t>();
43+
if (axis_value < 0)
44+
{
45+
axis_value += ifm_rank;
46+
}
47+
48+
auto acl_axis = acl_common::ToARMComputeAxis(ifm_rank, axis_value).value();
49+
auto reduce_type = node.param().is_arg_max ? ::arm_compute::ReductionOperation::ARG_IDX_MAX
50+
: ::arm_compute::ReductionOperation::ARG_IDX_MIN;
51+
auto fn = acl_common::generateLayer<arm_compute::CLArgMinMaxLayer>(
52+
ifm_tensor->handle(), acl_axis, ofm_tensor->handle(), reduce_type);
53+
54+
_return_fn = acl_common::asAclFunction(std::move(fn));
55+
}
56+
57+
} // namespace onert::backend::acl_cl
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../KernelGenerator.h"
18+
#include "../Validator.h"
19+
20+
#include <AclKernelGen.h>
21+
22+
namespace onert::backend::acl_cl
23+
{
24+
25+
void Validator::visit(const ir::operation::BatchToSpaceND &) { _supported = true; }
26+
27+
void KernelGenerator::visit(const ir::operation::BatchToSpaceND &node)
28+
{
29+
const auto ofm_index{node.getOutputs().at(0)};
30+
const auto ifm_index{node.getInputs().at(ir::operation::BatchToSpaceND::Input::INPUT)};
31+
const auto block_size_index{
32+
node.getInputs().at(ir::operation::BatchToSpaceND::Input::BLOCK_SIZE)};
33+
34+
const auto NNApiInputs = 2;
35+
if (node.getInputs().size() != NNApiInputs)
36+
{
37+
const auto crops_index{node.getInputs().at(ir::operation::BatchToSpaceND::Input::CROPS_DATA)};
38+
if (!_ctx.at(crops_index).isConstant())
39+
{
40+
throw std::runtime_error("Non-constant crops NYI for acl_cl backend BatchToSpaceND");
41+
}
42+
43+
auto crops = _ctx.at(crops_index).asVector<int32_t>();
44+
for (auto &&crop : crops)
45+
{
46+
if (crop != 0)
47+
{
48+
throw std::runtime_error("Non-zero crops NYI for acl_cl backend BatchToSpaceND");
49+
}
50+
}
51+
}
52+
53+
auto ofm_tensor = _tensor_reg->getAclTensor(ofm_index);
54+
auto ifm_tensor = _tensor_reg->getAclTensor(ifm_index);
55+
56+
if (!_ctx.at(block_size_index).data())
57+
throw std::runtime_error("ACL CL does not support dynamic block size for BatchToSpaceND");
58+
59+
auto block = _ctx.at(block_size_index).asVector<int32_t>();
60+
int32_t height = block[0];
61+
int32_t width = block[1];
62+
63+
auto fn = acl_common::generateLayer<arm_compute::CLBatchToSpaceLayer>(
64+
ifm_tensor->handle(), width, height, ofm_tensor->handle());
65+
66+
_return_fn = acl_common::asAclFunction(std::move(fn));
67+
}
68+
69+
} // namespace onert::backend::acl_cl
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../KernelGenerator.h"
18+
#include "../Validator.h"
19+
20+
#include <AclKernelGen.h>
21+
22+
namespace onert::backend::acl_cl
23+
{
24+
25+
void Validator::visit(const ir::operation::BinaryArithmetic &) { _supported = true; }
26+
27+
void KernelGenerator::visit(const ir::operation::BinaryArithmetic &node)
28+
{
29+
const auto ofm_index{node.getOutputs().at(0)};
30+
const auto lhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::LHS)};
31+
const auto rhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::RHS)};
32+
33+
const auto activation = node.param().activation;
34+
35+
auto ofm_tensor = _tensor_reg->getAclTensor(ofm_index);
36+
auto lhs_tensor = _tensor_reg->getAclTensor(lhs_index);
37+
auto rhs_tensor = _tensor_reg->getAclTensor(rhs_index);
38+
39+
const auto act_info = acl_common::asActivationLayerInfo(activation);
40+
41+
std::unique_ptr<arm_compute::IFunction> fn;
42+
switch (node.param().arithmetic_type)
43+
{
44+
case ir::operation::BinaryArithmetic::ArithmeticType::ADD:
45+
{
46+
arm_compute::CLArithmeticAddition::validate(lhs_tensor->info(), rhs_tensor->info(),
47+
ofm_tensor->info(),
48+
arm_compute::ConvertPolicy::SATURATE, act_info)
49+
.throw_if_error();
50+
fn = acl_common::generateLayer<arm_compute::CLArithmeticAddition>(
51+
lhs_tensor->handle(), rhs_tensor->handle(), ofm_tensor->handle(),
52+
arm_compute::ConvertPolicy::SATURATE, act_info);
53+
break;
54+
}
55+
case ir::operation::BinaryArithmetic::ArithmeticType::SUB:
56+
{
57+
arm_compute::CLArithmeticSubtraction::validate(lhs_tensor->info(), rhs_tensor->info(),
58+
ofm_tensor->info(),
59+
arm_compute::ConvertPolicy::SATURATE, act_info)
60+
.throw_if_error();
61+
fn = acl_common::generateLayer<arm_compute::CLArithmeticSubtraction>(
62+
lhs_tensor->handle(), rhs_tensor->handle(), ofm_tensor->handle(),
63+
arm_compute::ConvertPolicy::SATURATE, act_info);
64+
break;
65+
}
66+
case ir::operation::BinaryArithmetic::ArithmeticType::MUL:
67+
{
68+
arm_compute::CLPixelWiseMultiplication::validate(
69+
lhs_tensor->info(), rhs_tensor->info(), ofm_tensor->info(), 1.0,
70+
arm_compute::ConvertPolicy::SATURATE, arm_compute::RoundingPolicy::TO_NEAREST_EVEN,
71+
act_info)
72+
.throw_if_error();
73+
fn = acl_common::generateLayer<arm_compute::CLPixelWiseMultiplication>(
74+
lhs_tensor->handle(), rhs_tensor->handle(), ofm_tensor->handle(), 1.0, // scale
75+
arm_compute::ConvertPolicy::SATURATE, arm_compute::RoundingPolicy::TO_NEAREST_EVEN,
76+
act_info);
77+
break;
78+
}
79+
case ir::operation::BinaryArithmetic::ArithmeticType::DIV:
80+
{
81+
arm_compute::CLArithmeticDivision::validate(lhs_tensor->info(), rhs_tensor->info(),
82+
ofm_tensor->info(), act_info)
83+
.throw_if_error();
84+
fn = acl_common::generateLayer<arm_compute::CLArithmeticDivision>(
85+
lhs_tensor->handle(), rhs_tensor->handle(), ofm_tensor->handle(), act_info);
86+
break;
87+
}
88+
default:
89+
assert(false && "The BinaryArithmetic operation supports only binary arithmetic operations");
90+
break;
91+
}
92+
93+
_return_fn = acl_common::asAclFunction(std::move(fn));
94+
}
95+
96+
} // namespace onert::backend::acl_cl
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../KernelGenerator.h"
18+
#include "../Validator.h"
19+
20+
#include <AclKernelGen.h>
21+
22+
namespace onert::backend::acl_cl
23+
{
24+
25+
void Validator::visit(const ir::operation::Comparison &) { _supported = true; }
26+
27+
void KernelGenerator::visit(const ir::operation::Comparison &node)
28+
{
29+
const auto output_index{node.getOutputs().at(0)};
30+
const auto input0_index{node.getInputs().at(ir::operation::Comparison::Input::INPUT0)};
31+
const auto input1_index{node.getInputs().at(ir::operation::Comparison::Input::INPUT1)};
32+
33+
const auto comparison_type = node.param().comparison_type;
34+
35+
auto output_tensor = _tensor_reg->getAclTensor(output_index);
36+
auto input0_tensor = _tensor_reg->getAclTensor(input0_index);
37+
auto input1_tensor = _tensor_reg->getAclTensor(input1_index);
38+
39+
auto fn = acl_common::generateLayer<arm_compute::CLComparison>(
40+
input0_tensor->handle(), input1_tensor->handle(), output_tensor->handle(),
41+
(arm_compute::ComparisonOperation)comparison_type);
42+
43+
_return_fn = acl_common::asAclFunction(std::move(fn));
44+
}
45+
46+
} // namespace onert::backend::acl_cl
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2025 Samsung Electronics Co., Ltd. All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "../KernelGenerator.h"
18+
#include "../Validator.h"
19+
20+
#include <AclKernelGen.h>
21+
#include "exec/NopFunction.h"
22+
23+
namespace onert::backend::acl_cl
24+
{
25+
26+
void Validator::visit(const ir::operation::Concat &) { _supported = true; }
27+
28+
void KernelGenerator::visit(const ir::operation::Concat &node)
29+
{
30+
const auto ofm_index{node.getOutputs().at(0)};
31+
32+
std::vector<ir::OperandIndex> input_indexes;
33+
34+
for (const auto &input : node.getInputs())
35+
input_indexes.emplace_back(input);
36+
37+
const auto axis = node.param().axis;
38+
39+
// Concat elimination check
40+
bool eliminated = _tensor_builder->areSubTensorsOf(ofm_index, node.getInputs());
41+
if (eliminated)
42+
{
43+
// If concat eliminated, return a NOP IFunction
44+
VERBOSE(acl_cl_KernelGenerator_Concat) << "Concat eliminated" << std::endl;
45+
_return_fn = std::make_unique<exec::NopFunction>();
46+
return;
47+
}
48+
49+
auto output_tensor = _tensor_reg->getAclTensor(ofm_index);
50+
std::vector<const ::arm_compute::ICLTensor *> input_tensors;
51+
for (const auto &ifm_ind : input_indexes)
52+
input_tensors.emplace_back(_tensor_reg->getAclTensor(ifm_ind)->handle());
53+
54+
std::unique_ptr<::arm_compute::IFunction> fn;
55+
if (input_indexes.size() < 2)
56+
{
57+
::arm_compute::ICLTensor *input_tesor =
58+
_tensor_reg->getAclTensor(input_indexes.at(0))->handle();
59+
60+
fn = acl_common::generateLayer<arm_compute::CLCopy>(input_tesor, output_tensor->handle());
61+
}
62+
else
63+
{
64+
const auto rank = _ctx.at(ofm_index).shape().rank();
65+
const auto fixed_axis = acl_common::ToARMComputeAxis(rank, axis).value();
66+
fn = acl_common::generateLayer<::arm_compute::CLConcatenateLayer>(
67+
input_tensors, output_tensor->handle(), fixed_axis);
68+
}
69+
70+
_return_fn = acl_common::asAclFunction(std::move(fn));
71+
}
72+
73+
} // namespace onert::backend::acl_cl

0 commit comments

Comments
 (0)