Skip to content

Commit 11a2dad

Browse files
committed
Calculate CMSIS-NN buffer size with respect to architecture extensions
This correctly calculates the buffer sizes for a variety of targets based on the `-mcpu` and `-mattr` flags passed to the `cmsis-nn` code generator. Added for Conv2d, Depthwise Conv2d and Average Pool.
1 parent 75cd670 commit 11a2dad

File tree

10 files changed

+718
-8
lines changed

10 files changed

+718
-8
lines changed

cmake/modules/contrib/CMSISNN.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# under the License.
1717

1818
if(USE_CMSISNN)
19+
add_definitions(-DTVM_USE_CMSISNN)
1920
message(STATUS "Build with CMSIS-NN support")
2021
tvm_file_glob(GLOB RELAY_CONTRIB_CMSISNN_SRCS src/relay/backend/contrib/cmsisnn/*.cc)
2122
list(APPEND COMPILER_SRCS ${RELAY_CONTRIB_CMSISNN_SRCS})

python/tvm/driver/tvmc/composite_target.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"pass_pipeline": partition_for_arm_compute_lib,
5454
},
5555
"cmsis-nn": {
56-
"config_key": None,
56+
"config_key": "relay.ext.cmsisnn.options",
5757
"pass_pipeline": partition_for_cmsisnn,
5858
},
5959
"ethos-n77": {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include <tvm/ir/attrs.h>
21+
#include <tvm/ir/transform.h>
22+
23+
#include "compiler_attrs.h"
24+
25+
namespace tvm {
26+
namespace relay {
27+
namespace contrib {
28+
namespace cmsisnn {
29+
30+
int Conv2dBufferSize(CMSISNNFlags flags, int32_t padding_w, int32_t padding_h, int32_t input_n,
31+
int32_t input_h, int32_t input_c, int32_t output_h, int32_t output_w,
32+
int32_t stride_w, int32_t stride_h, int32_t filter_w, int32_t filter_h) {
33+
bool is1x1 = (padding_w == 0) && (padding_h == 0) && (input_c % 4 == 0) && (stride_w == 1) &&
34+
(stride_h == 1) && (filter_w == 1) && (filter_h == 1);
35+
bool is1xN =
36+
(output_h == 1) && (input_h == 1) && (filter_h == 1) && (output_w % 4 == 0) && (input_n == 1);
37+
38+
if (is1x1) {
39+
return 0;
40+
}
41+
42+
if (is1xN) {
43+
if (flags.dsp && !flags.mve) {
44+
return (2 * input_c * filter_w * filter_h) * (int32_t)sizeof(int16_t);
45+
}
46+
return 0;
47+
}
48+
49+
if (flags.dsp) {
50+
return (2 * input_c * filter_w * filter_h) * (int32_t)sizeof(int16_t);
51+
}
52+
return 0;
53+
}
54+
55+
int DepthwiseConv2dBufferSize(CMSISNNFlags flags, int32_t input_n, int32_t input_c,
56+
int32_t output_c, int32_t filter_w, int32_t filter_h) {
57+
if (input_c == output_c && input_n == 1) {
58+
if (flags.mve) {
59+
return (2 * input_c * filter_w * filter_h) * (int32_t)sizeof(int16_t) + 4;
60+
}
61+
if (flags.dsp) {
62+
return (input_c * filter_w * filter_h) * (int32_t)sizeof(int16_t);
63+
}
64+
}
65+
return 0;
66+
}
67+
68+
int AvgPoolBufferSize(CMSISNNFlags flags, int32_t input_c) {
69+
if (flags.dsp && !flags.mve) {
70+
return (input_c * sizeof(int32_t));
71+
}
72+
return 0;
73+
}
74+
75+
} // namespace cmsisnn
76+
} // namespace contrib
77+
} // namespace relay
78+
} // namespace tvm
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/*!
21+
* \file src/relay/backend/contrib/cmsisnn/buffer_size.h
22+
* \brief CMSIS-NN Buffer Size calculation functions
23+
*/
24+
25+
#ifndef TVM_RELAY_BACKEND_CONTRIB_CMSISNN_BUFFER_SIZE_H_
26+
#define TVM_RELAY_BACKEND_CONTRIB_CMSISNN_BUFFER_SIZE_H_
27+
28+
#include <tvm/ir/transform.h>
29+
30+
#include "compiler_attrs.h"
31+
32+
namespace tvm {
33+
namespace relay {
34+
namespace contrib {
35+
namespace cmsisnn {
36+
37+
/*!
38+
* \brief Calculates the appropriate buffer size for CMSIS-NN Convolutions
39+
* See:
40+
* https://github.com/ARM-software/CMSIS_5/blob/8c60448c0e1e50e426180b26db9bc31ddf774361/CMSIS/NN/Source/ConvolutionFunctions/arm_convolve_wrapper_s8.c#L108-L127
41+
*
42+
* \param flags - CMSIS-NN feature flags
43+
* \param padding_w - Width padding
44+
* \param padding_h - Height padding
45+
* \param input_n - Input batch size
46+
* \param input_h - Input height
47+
* \param input_c - Input channels
48+
* \param output_h - Output height
49+
* \param output_w - Output width
50+
* \param stride_w - Stride width
51+
* \param stride_h - Stride height
52+
* \param filter_w - Filter width
53+
* \param filter_h - Filter height
54+
*
55+
* \return Size of buffer to allocate for convolution
56+
*/
57+
int Conv2dBufferSize(CMSISNNFlags flags, int32_t padding_w, int32_t padding_h, int32_t input_n,
58+
int32_t input_h, int32_t input_c, int32_t output_h, int32_t output_w,
59+
int32_t stride_w, int32_t stride_h, int32_t filter_w, int32_t filter_h);
60+
61+
/*!
62+
* \brief Calculates the appropriate buffer size for CMSIS-NN Depthwise Convolutions
63+
* See:
64+
* https://github.com/ARM-software/CMSIS_5/blob/325443e52637b6c7eedbd160d238a6c462e89c9f/CMSIS/NN/Source/ConvolutionFunctions/arm_depthwise_conv_wrapper_s8.c#L115-L129
65+
*
66+
* \param flags - CMSIS-NN feature flags
67+
* \param input_n - Input batch size
68+
* \param input_c - Input channels
69+
* \param output_c - Output channels
70+
* \param filter_w - Filter width
71+
* \param filter_h - Filter height
72+
*
73+
* \return Size of buffer to allocate for depthwise convolution
74+
*/
75+
int DepthwiseConv2dBufferSize(CMSISNNFlags flags, int32_t input_n, int32_t input_c,
76+
int32_t output_c, int32_t filter_w, int32_t filter_h);
77+
78+
/*!
79+
* \brief Calculates the appropriate buffer size for CMSIS-NN Average Pooling
80+
* See:
81+
* https://github.com/ARM-software/CMSIS_5/blob/bff28575f0c96a4ee9008947fea2b018a69b4900/CMSIS/NN/Source/PoolingFunctions/arm_avgpool_s8.c#L388-L398
82+
*
83+
* \param input_c - Input channels
84+
*
85+
* \return Size of buffer to allocate for average pooling
86+
*/
87+
int AvgPoolBufferSize(CMSISNNFlags flags, int32_t input_c);
88+
89+
} // namespace cmsisnn
90+
} // namespace contrib
91+
} // namespace relay
92+
} // namespace tvm
93+
94+
#endif // TVM_RELAY_BACKEND_CONTRIB_CMSISNN_BUFFER_SIZE_H_
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
#include "compiler_attrs.h"
20+
21+
#include <tvm/ir/attrs.h>
22+
#include <tvm/ir/transform.h>
23+
24+
#include <string>
25+
26+
namespace tvm {
27+
namespace relay {
28+
namespace contrib {
29+
namespace cmsisnn {
30+
31+
static const char* mveCPUs[] = {"cortex-m55"};
32+
static const char* dspCPUs[] = {"cortex-m7", "cortex-m33", "cortex-m35p"};
33+
34+
TVM_REGISTER_NODE_TYPE(CMSISNNCompilerConfigNode);
35+
TVM_REGISTER_PASS_CONFIG_OPTION("relay.ext.cmsisnn.options", CMSISNNCompilerConfig);
36+
37+
template <typename Container>
38+
static inline bool MatchesCpu(std::string mcpu, const Container& cpus) {
39+
auto matches_cpu = [mcpu](const char* cpu) { return mcpu.find(cpu) == 0; };
40+
return std::find_if(std::begin(cpus), std::end(cpus), matches_cpu) != std::end(cpus);
41+
}
42+
43+
static inline bool HasFlag(std::string attr, std::string flag) {
44+
return attr.find(flag) != std::string::npos;
45+
}
46+
47+
CMSISNNFlags GetCompilerFlags(const tvm::transform::PassContext& ctx) {
48+
auto cfg = ctx->GetConfig<CMSISNNCompilerConfig>("relay.ext.cmsisnn.options");
49+
if (!cfg.defined()) {
50+
return kNoExt;
51+
}
52+
53+
std::string mcpu = cfg.value()->mcpu;
54+
std::string mattr = cfg.value()->mattr;
55+
56+
bool nomve = HasFlag(mcpu, "+nomve") || HasFlag(mattr, "+nomve");
57+
bool nodsp = HasFlag(mcpu, "+nodsp") || HasFlag(mattr, "+nodsp");
58+
59+
auto has_mve = MatchesCpu(mcpu, mveCPUs);
60+
if (has_mve && !nomve && !nodsp) {
61+
return kHasMVE;
62+
}
63+
64+
auto has_dsp = MatchesCpu(mcpu, dspCPUs);
65+
if (has_dsp && !nodsp) {
66+
return kHasDSP;
67+
}
68+
69+
return kNoExt;
70+
}
71+
72+
} // namespace cmsisnn
73+
} // namespace contrib
74+
} // namespace relay
75+
} // namespace tvm
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
/*!
21+
* \file src/relay/backend/contrib/cmsisnn/compiler_attrs.h
22+
* \brief CMSIS-NN Compiler Attribute functionality
23+
*/
24+
25+
#ifndef TVM_RELAY_BACKEND_CONTRIB_CMSISNN_COMPILER_ATTRS_H_
26+
#define TVM_RELAY_BACKEND_CONTRIB_CMSISNN_COMPILER_ATTRS_H_
27+
28+
#include <tvm/ir/transform.h>
29+
30+
namespace tvm {
31+
namespace relay {
32+
namespace contrib {
33+
namespace cmsisnn {
34+
35+
/*! \brief Attributes to store the compiler options for CMSIS-NN. */
36+
struct CMSISNNCompilerConfigNode : public tvm::AttrsNode<CMSISNNCompilerConfigNode> {
37+
String mcpu;
38+
String mattr;
39+
40+
TVM_DECLARE_ATTRS(CMSISNNCompilerConfigNode, "ext.attrs.CMSISNNCompilerConfigNode") {
41+
TVM_ATTR_FIELD(mcpu)
42+
.describe(
43+
"The CPU to configure CMSIS-NN for (i.e. cortex-m55, cortex-m4), can also include "
44+
"attributes (i.e. cortex-m55+nomve)")
45+
.set_default("");
46+
TVM_ATTR_FIELD(mattr)
47+
.describe("The attributes to configure CMSIS-NN (i.e. +nodsp, +nomve)")
48+
.set_default("");
49+
}
50+
};
51+
52+
class CMSISNNCompilerConfig : public Attrs {
53+
public:
54+
TVM_DEFINE_NOTNULLABLE_OBJECT_REF_METHODS(CMSISNNCompilerConfig, Attrs,
55+
CMSISNNCompilerConfigNode);
56+
};
57+
58+
/*! \brief Flags to configure the calculations for CMSIS-NN. */
59+
struct CMSISNNFlags {
60+
bool dsp; // Enable or disable dsp buffers
61+
bool mve; // Enable or disable mve buffers
62+
};
63+
64+
constexpr CMSISNNFlags kNoExt = {.dsp = false, .mve = false};
65+
constexpr CMSISNNFlags kHasDSP = {.dsp = true, .mve = false};
66+
constexpr CMSISNNFlags kHasMVE = {.dsp = true, .mve = true};
67+
68+
CMSISNNFlags GetCompilerFlags(const tvm::transform::PassContext& ctx);
69+
70+
} // namespace cmsisnn
71+
} // namespace contrib
72+
} // namespace relay
73+
} // namespace tvm
74+
75+
#endif // TVM_RELAY_BACKEND_CONTRIB_CMSISNN_COMPILER_ATTRS_H_

0 commit comments

Comments
 (0)