Skip to content

Commit 77596e7

Browse files
dsharletgxnnpack-bot
authored andcommitted
Add xnn_define_static_constant_pad_v2 and deprecate xnn_define_static_constant_pad
`xnn_define_static_constant_pad_v2` takes `num_padding_dims` as a parameter, instead of inferring it from the input value's shape as `xnn_define_static_constant_pad` does. This is necessary because we infer the rank of values in the subgraph. If the rank inference changes the rank of the input value after the padding node is defined, the padding node is unlikely to behave as intended. This change makes the intended behavior explicit. See #9775 for more context. PiperOrigin-RevId: 890668243
1 parent 96f529c commit 77596e7

File tree

11 files changed

+129
-99
lines changed

11 files changed

+129
-99
lines changed

include/xnnpack.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,16 +1370,27 @@ XNN_DEPRECATED enum xnn_status xnn_define_squared_difference(
13701370
/// Define a Constant Pad Node with static padding specification and add it to a Subgraph.
13711371
///
13721372
/// @param subgraph - a Subgraph object that will own the created Node.
1373+
/// @param num_padding_dims - number of dimensions to pad.
13731374
/// @param pre_paddings - number of padding elements to insert before input elements for every dimension. This array
1374-
/// must have as many elements as the number of dimensions in the input tensor.
1375+
/// must have @num_padding_dims elements.
13751376
/// @param post_paddings - number of padding elements to insert after input elements for every dimension. This array
1376-
/// must have as many elements as the number of dimensions in the input tensor.
1377+
/// must have @num_padding_dims elements.
13771378
/// @param padding_value - constant value used to initialize padding elements.
13781379
/// @param input_id - Value ID for the input tensor. The input tensor must be defined in the @a subgraph.
13791380
/// @param output_id - Value ID for the output tensor. The output tensor must be defined in the @a subgraph, and its
13801381
/// shape must match the shape of the input tensor with padding.
13811382
/// @param flags - binary features of the Constant Pad Node. No supported flags are currently defined.
1382-
enum xnn_status xnn_define_static_constant_pad(
1383+
enum xnn_status xnn_define_static_constant_pad_v2(
1384+
xnn_subgraph_t subgraph,
1385+
size_t num_padding_dims,
1386+
const size_t* pre_paddings,
1387+
const size_t* post_paddings,
1388+
float padding_value,
1389+
uint32_t input_id,
1390+
uint32_t output_id,
1391+
uint32_t flags);
1392+
1393+
XNN_DEPRECATED enum xnn_status xnn_define_static_constant_pad(
13831394
xnn_subgraph_t subgraph,
13841395
const size_t* pre_paddings,
13851396
const size_t* post_paddings,

src/subgraph/deprecated.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
#include <inttypes.h>
12
#include <math.h>
23
#include <stddef.h>
34
#include <stdint.h>
45

56
#include "include/xnnpack.h"
7+
#include "src/xnnpack/log.h"
8+
#include "src/xnnpack/node-type.h"
69
#include "src/xnnpack/subgraph.h"
710

811
enum xnn_status xnn_define_add2(xnn_subgraph_t subgraph, float output_min,
@@ -386,3 +389,22 @@ enum xnn_status xnn_define_even_split4(xnn_subgraph_t subgraph, int32_t split_di
386389
const uint32_t outputs_id[4] = {output1_id, output2_id, output3_id, output4_id};
387390
return xnn_define_even_split(subgraph, split_dim, input_id, /*num_outputs=*/4, outputs_id, flags);
388391
}
392+
393+
enum xnn_status xnn_define_static_constant_pad(
394+
xnn_subgraph_t subgraph,
395+
const size_t* pre_paddings,
396+
const size_t* post_paddings,
397+
float padding_value,
398+
uint32_t input_id,
399+
uint32_t output_id,
400+
uint32_t flags) {
401+
if (input_id >= subgraph->num_values) {
402+
xnn_log_error(
403+
"failed to define %s operator with input ID #%" PRIu32 ": invalid Value ID",
404+
xnn_node_type_to_string(xnn_node_type_static_constant_pad), input_id);
405+
return xnn_status_invalid_parameter;
406+
}
407+
size_t num_padding_dims = subgraph->values[input_id].shape.num_dims;
408+
return xnn_define_static_constant_pad_v2(subgraph, num_padding_dims, pre_paddings,
409+
post_paddings, padding_value, input_id, output_id, flags);
410+
}

src/subgraph/static-constant-pad.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,9 @@ static enum xnn_status setup_constant_pad_operator(
173173
}
174174
}
175175

176-
enum xnn_status xnn_define_static_constant_pad(
176+
enum xnn_status xnn_define_static_constant_pad_v2(
177177
xnn_subgraph_t subgraph,
178+
size_t num_padding_dims,
178179
const size_t* pre_paddings,
179180
const size_t* post_paddings,
180181
float padding_value,
@@ -187,6 +188,13 @@ enum xnn_status xnn_define_static_constant_pad(
187188
return status;
188189
}
189190

191+
if (num_padding_dims > XNN_MAX_TENSOR_DIMS) {
192+
xnn_log_error(
193+
"failed to define %s operator with %zu dims: maximum number of dimensions is %d",
194+
xnn_node_type_to_string(xnn_node_type_static_constant_pad), num_padding_dims, XNN_MAX_TENSOR_DIMS);
195+
return xnn_status_invalid_parameter;
196+
}
197+
190198
if (input_id >= subgraph->num_values) {
191199
xnn_log_error(
192200
"failed to define %s operator with input ID #%" PRIu32 ": invalid Value ID",
@@ -244,9 +252,11 @@ enum xnn_status xnn_define_static_constant_pad(
244252
return xnn_status_out_of_memory;
245253
}
246254

247-
const size_t num_dims = subgraph->values[input_id].shape.num_dims;
248-
memcpy(&node->params.static_pad.pre_paddings, pre_paddings, num_dims * sizeof(size_t));
249-
memcpy(&node->params.static_pad.post_paddings, post_paddings, num_dims * sizeof(size_t));
255+
node->params.static_pad.num_padding_dims = num_padding_dims;
256+
memset(&node->params.static_pad.pre_paddings, 0, XNN_MAX_TENSOR_DIMS * sizeof(size_t));
257+
memset(&node->params.static_pad.post_paddings, 0, XNN_MAX_TENSOR_DIMS * sizeof(size_t));
258+
memcpy(&node->params.static_pad.pre_paddings, pre_paddings, num_padding_dims * sizeof(size_t));
259+
memcpy(&node->params.static_pad.post_paddings, post_paddings, num_padding_dims * sizeof(size_t));
250260
switch (output_value->datatype) {
251261
case xnn_datatype_fp32:
252262
node->params.static_pad.padding_value = float_as_uint32(padding_value);

src/xnnpack/subgraph.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ struct xnn_node {
364364
struct {
365365
size_t pre_paddings[XNN_MAX_TENSOR_DIMS];
366366
size_t post_paddings[XNN_MAX_TENSOR_DIMS];
367+
size_t num_padding_dims;
367368
uint32_t padding_value;
368369
} static_pad;
369370
struct {

test/subgraph/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ xnnpack_unit_test(
342342
"//:node_type",
343343
"//:operator_h",
344344
"//:params",
345-
"//:subgraph",
346345
"//:subgraph_h",
347346
"//:xnnpack_h",
348347
"//test:replicable_random_device",

test/subgraph/fusion.cc

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,8 @@ TEST(CONSTANT_PAD_THEN_CONVOLUTION, fusion) {
341341
uint32_t filter_id = 2;
342342
uint32_t bias_id = 3;
343343
uint32_t output_id = 4;
344-
size_t pre_paddings[4] = {0, 2, 4, 0};
345-
size_t post_paddings[4] = {0, 6, 8, 0};
344+
std::vector<size_t> pre_paddings = {0, 2, 4, 0};
345+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
346346
float padding_value = 0.0f;
347347

348348
tester.AddInputTensorF32({1, 254, 254, 3}, input_id)
@@ -386,8 +386,8 @@ TEST(CONSTANT_PAD_THEN_CONVOLUTION, fusion_quantized_int8) {
386386
uint32_t filter_id = 2;
387387
uint32_t bias_id = 3;
388388
uint32_t output_id = 4;
389-
size_t pre_paddings[4] = {0, 2, 4, 0};
390-
size_t post_paddings[4] = {0, 6, 8, 0};
389+
std::vector<size_t> pre_paddings = {0, 2, 4, 0};
390+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
391391
float padding_value = 0.0f;
392392
using qint8 = xnnpack::quantized<int8_t>;
393393
using qint32 = xnnpack::quantized<int32_t>;
@@ -446,8 +446,8 @@ TEST(CONSTANT_PAD_THEN_CONVOLUTION,
446446
uint32_t bias_id = 3;
447447
uint32_t output_id = 4;
448448
// Non-zero pre-padding in the N or C dimension.
449-
size_t pre_paddings[4] = {1, 2, 4, 0};
450-
size_t post_paddings[4] = {0, 6, 8, 0};
449+
std::vector<size_t> pre_paddings = {1, 2, 4, 0};
450+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
451451
float padding_value = 0.0f;
452452

453453
tester.AddInputTensorF32({1, 254, 254, 3}, input_id)
@@ -480,8 +480,8 @@ TEST(CONSTANT_PAD_THEN_CONVOLUTION, not_fused_due_to_padding_value_not_zero) {
480480
uint32_t filter_id = 2;
481481
uint32_t bias_id = 3;
482482
uint32_t output_id = 4;
483-
size_t pre_paddings[4] = {1, 2, 4, 0};
484-
size_t post_paddings[4] = {0, 6, 8, 0};
483+
std::vector<size_t> pre_paddings = {1, 2, 4, 0};
484+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
485485
float padding_value = 1.0f;
486486

487487
tester.AddInputTensorF32({1, 254, 254, 3}, input_id)
@@ -514,8 +514,8 @@ TEST(CONSTANT_PAD_THEN_DEPTHWISE_CONVOLUTION, fusion) {
514514
uint32_t filter_id = 2;
515515
uint32_t bias_id = 3;
516516
uint32_t output_id = 4;
517-
size_t pre_paddings[4] = {0, 2, 4, 0};
518-
size_t post_paddings[4] = {0, 6, 8, 0};
517+
std::vector<size_t> pre_paddings = {0, 2, 4, 0};
518+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
519519
float padding_value = 0.0f;
520520
tester.AddInputTensorF32({1, 128, 128, 4}, input_id)
521521
.AddDynamicTensorF32({1, 136, 140, 4}, intermediate_id)
@@ -558,8 +558,8 @@ TEST(CONSTANT_PAD_THEN_DEPTHWISE_CONVOLUTION,
558558
uint32_t bias_id = 3;
559559
uint32_t output_id = 4;
560560
// Non-zero pre-padding in the N or C dimension.
561-
size_t pre_paddings[4] = {1, 2, 4, 0};
562-
size_t post_paddings[4] = {0, 6, 8, 0};
561+
std::vector<size_t> pre_paddings = {1, 2, 4, 0};
562+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
563563
float padding_value = 0.0f;
564564
tester.AddInputTensorF32({1, 128, 128, 4}, input_id)
565565
.AddDynamicTensorF32({2, 136, 140, 4}, intermediate_id)
@@ -590,8 +590,8 @@ TEST(CONSTANT_PAD_THEN_DEPTHWISE_CONVOLUTION,
590590
uint32_t filter_id = 2;
591591
uint32_t bias_id = 3;
592592
uint32_t output_id = 4;
593-
size_t pre_paddings[4] = {0, 2, 4, 0};
594-
size_t post_paddings[4] = {0, 6, 8, 0};
593+
std::vector<size_t> pre_paddings = {0, 2, 4, 0};
594+
std::vector<size_t> post_paddings = {0, 6, 8, 0};
595595
float padding_value = 1.0f;
596596
tester.AddInputTensorF32({1, 128, 128, 4}, input_id)
597597
.AddDynamicTensorF32({1, 136, 140, 4}, intermediate_id)

test/subgraph/static-constant-pad.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ void TestImpl(size_t rank) {
2626
ASSERT_EQ(xnn_status_success, xnn_initialize(nullptr /* allocator */));
2727

2828
for (auto _ : FuzzTest(std::chrono::milliseconds(250))) {
29-
std::vector<size_t> pre_padding = random_shape(rng, rank, 0, 3);
30-
std::vector<size_t> post_padding = random_shape(rng, rank, 0, 3);
29+
size_t padding_rank = std::uniform_int_distribution<size_t>(1, rank)(rng);
30+
std::vector<size_t> pre_padding = random_shape(rng, padding_rank, 0, 3);
31+
std::vector<size_t> post_padding = random_shape(rng, padding_rank, 0, 3);
3132
float pad_value = 1.0f;
3233

3334
xnn_quantization_params quantization =
@@ -40,6 +41,10 @@ void TestImpl(size_t rank) {
4041
.AddConstantPad(pre_padding, post_padding, pad_value, 0, 1)
4142
.CreateRuntime();
4243

44+
// The test code needs the padding to be the same rank as the input/output.
45+
pre_padding.resize(rank);
46+
post_padding.resize(rank);
47+
4348
for (int reshape = 0; reshape < 2; ++reshape) {
4449
std::vector<size_t> shape = random_shape(rng, rank);
4550

@@ -48,7 +53,7 @@ void TestImpl(size_t rank) {
4853
input.generate([&]() { return generator(rng); });
4954

5055
std::vector<size_t> output_shape(shape);
51-
for (size_t i = 0; i < rank; ++i) {
56+
for (size_t i = 0; i < padding_rank; ++i) {
5257
output_shape[i] += pre_padding[i] + post_padding[i];
5358
}
5459

test/subgraph/subgraph-fp16.cc

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ TEST(SUBGRAPH_FP16, fully_connected_f16_weights_no_biases) {
222222

223223
TEST(SUBGRAPH_FP16, value_both_external_output_and_input) {
224224
SubgraphTester tester(4);
225-
std::array<size_t, 4> pre_paddings = {0, 1, 0, 0};
226-
std::array<size_t, 4> post_paddings = {0, 1, 0, 0};
225+
std::vector<size_t> pre_paddings = {0, 1, 0, 0};
226+
std::vector<size_t> post_paddings = {0, 1, 0, 0};
227227
// external input[0]
228228
// /
229229
// [constant pad]
@@ -239,7 +239,7 @@ TEST(SUBGRAPH_FP16, value_both_external_output_and_input) {
239239
.AddDynamicTensorF32({1, 1, 1, 3}, 1)
240240
.AddOutputTensorF32({1, 4, 2, 3}, 2)
241241
.AddOutputTensorF32({1, 4, 2, 3}, 3)
242-
.AddConstantPad(pre_paddings.data(), post_paddings.data(), 0.0f, 0, 2)
242+
.AddConstantPad(pre_paddings, post_paddings, 0.0f, 0, 2)
243243
.AddAddition(2, 1, 3)
244244
.Optimize()
245245
.RewriteForFp16();
@@ -940,14 +940,13 @@ TEST(SUBGRAPH_FP16_DYNAMIC_FULLY_CONNECTED,
940940
const uint32_t input2_id = 1;
941941
const uint32_t weights_id = 3;
942942
const uint32_t fully_connected_out_id = 2;
943-
std::array<size_t, 4> pre_paddings = {1, 0, 0, 0};
944-
std::array<size_t, 4> post_paddings = {0, 0, 0, 0};
943+
std::vector<size_t> pre_paddings = {1, 0, 0, 0};
944+
std::vector<size_t> post_paddings = {0, 0, 0, 0};
945945
tester.AddInputTensorF32({1, 5, 5, 3}, input_id)
946946
.AddInputTensorF32({1, 1, 1, 3}, input2_id)
947947
.AddOutputTensorF32({1, 5, 5, 2}, fully_connected_out_id)
948948
.AddDynamicTensorF32({2, 1, 1, 3}, weights_id)
949-
.AddConstantPad(pre_paddings.data(), post_paddings.data(), 0.0f,
950-
input2_id, weights_id)
949+
.AddConstantPad(pre_paddings, post_paddings, 0.0f, input2_id, weights_id)
951950
.AddFullyConnected(input_id, weights_id,
952951
/*bias_id=*/XNN_INVALID_VALUE_ID,
953952
fully_connected_out_id)
@@ -974,15 +973,14 @@ TEST(SUBGRAPH_FP16_DYNAMIC_FULLY_CONNECTED,
974973
const uint32_t weights_id = 3;
975974
const uint32_t bias_id = 4;
976975
const uint32_t fully_connected_out_id = 2;
977-
std::array<size_t, 4> pre_paddings = {1, 0, 0, 0};
978-
std::array<size_t, 4> post_paddings = {0, 0, 0, 0};
976+
std::vector<size_t> pre_paddings = {1, 0, 0, 0};
977+
std::vector<size_t> post_paddings = {0, 0, 0, 0};
979978
tester.AddInputTensorF32({1, 5, 5, 3}, input_id)
980979
.AddInputTensorF32({1, 1, 1, 3}, input2_id)
981980
.AddOutputTensorF32({1, 5, 5, 2}, fully_connected_out_id)
982981
.AddDynamicTensorF32({2, 1, 1, 3}, weights_id)
983982
.AddStaticTensorF32({2}, TensorType::kDense, bias_id)
984-
.AddConstantPad(pre_paddings.data(), post_paddings.data(), 0.0f,
985-
input2_id, weights_id)
983+
.AddConstantPad(pre_paddings, post_paddings, 0.0f, input2_id, weights_id)
986984
.AddFullyConnected(input_id, weights_id, bias_id, fully_connected_out_id)
987985
.Optimize()
988986
.RewriteForFp16();
@@ -1007,15 +1005,14 @@ TEST(SUBGRAPH_FP16_DYNAMIC_FULLY_CONNECTED,
10071005
const uint32_t weights_id = 3;
10081006
const uint32_t bias_id = 4;
10091007
const uint32_t fully_connected_out_id = 2;
1010-
std::array<size_t, 4> pre_paddings = {1};
1011-
std::array<size_t, 4> post_paddings = {0};
1008+
std::vector<size_t> pre_paddings = {1};
1009+
std::vector<size_t> post_paddings = {0};
10121010
tester.AddInputTensorF32({1, 5, 5, 3}, input_id)
10131011
.AddInputTensorF32({1}, input2_id)
10141012
.AddOutputTensorF32({1, 5, 5, 2}, fully_connected_out_id)
10151013
.AddStaticTensorF32({2, 1, 1, 3}, TensorType::kDense, weights_id)
10161014
.AddDynamicTensorF32({2}, bias_id)
1017-
.AddConstantPad(pre_paddings.data(), post_paddings.data(), 0.0f,
1018-
input2_id, bias_id)
1015+
.AddConstantPad(pre_paddings, post_paddings, 0.0f, input2_id, bias_id)
10191016
.AddFullyConnected(input_id, weights_id, bias_id, fully_connected_out_id)
10201017
.Optimize()
10211018
.RewriteForFp16();
@@ -1042,21 +1039,21 @@ TEST(SUBGRAPH_FP16_DYNAMIC_FULLY_CONNECTED,
10421039
const uint32_t bias_id = 4;
10431040
const uint32_t fully_connected_out_id = 5;
10441041

1045-
std::array<size_t, 4> weights_pre_paddings = {1, 0, 0, 0};
1046-
std::array<size_t, 4> weights_post_paddings = {0, 0, 0, 0};
1047-
std::array<size_t, 4> bias_pre_paddings = {1};
1048-
std::array<size_t, 4> bias_post_paddings = {0};
1042+
std::vector<size_t> weights_pre_paddings = {1, 0, 0, 0};
1043+
std::vector<size_t> weights_post_paddings = {0, 0, 0, 0};
1044+
std::vector<size_t> bias_pre_paddings = {1};
1045+
std::vector<size_t> bias_post_paddings = {0};
10491046

10501047
tester.AddInputTensorF32({1, 5, 5, 3}, input_id)
10511048
.AddInputTensorF32({1, 1, 1, 3}, input2_id)
10521049
.AddInputTensorF32({1}, input3_id)
10531050
.AddOutputTensorF32({1, 5, 5, 2}, fully_connected_out_id)
10541051
.AddDynamicTensorF32({2, 1, 1, 3}, weights_id)
10551052
.AddDynamicTensorF32({2}, bias_id)
1056-
.AddConstantPad(weights_pre_paddings.data(), weights_post_paddings.data(),
1057-
0.0f, input2_id, weights_id)
1058-
.AddConstantPad(bias_pre_paddings.data(), bias_post_paddings.data(), 0.0f,
1059-
input3_id, bias_id)
1053+
.AddConstantPad(weights_pre_paddings, weights_post_paddings, 0.0f,
1054+
input2_id, weights_id)
1055+
.AddConstantPad(bias_pre_paddings, bias_post_paddings, 0.0f, input3_id,
1056+
bias_id)
10601057
.AddFullyConnected(input_id, weights_id, bias_id, fully_connected_out_id)
10611058
.Optimize()
10621059
.RewriteForFp16();

test/subgraph/subgraph-tester.cc

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -285,25 +285,14 @@ SubgraphTester& SubgraphTester::AddConcatenate(size_t axis,
285285
return *this;
286286
}
287287

288-
SubgraphTester& SubgraphTester::AddConstantPad(const size_t* pre_paddings,
289-
const size_t* post_paddings,
290-
float padding_value,
291-
uint32_t input_id,
292-
uint32_t output_id) {
293-
const xnn_status status = xnn_define_static_constant_pad(
294-
subgraph_.get(), pre_paddings, post_paddings, padding_value, input_id,
295-
output_id, /*flags=*/0);
296-
EXPECT_EQ(status, xnn_status_success);
297-
return *this;
298-
}
299-
300288
SubgraphTester& SubgraphTester::AddConstantPad(
301289
const std::vector<size_t>& pre_paddings,
302290
const std::vector<size_t>& post_paddings, float padding_value,
303291
uint32_t input_id, uint32_t output_id) {
304-
const xnn_status status = xnn_define_static_constant_pad(
305-
subgraph_.get(), pre_paddings.data(), post_paddings.data(), padding_value,
306-
input_id, output_id, /*flags=*/0);
292+
assert(pre_paddings.size() == post_paddings.size());
293+
const xnn_status status = xnn_define_static_constant_pad_v2(
294+
subgraph_.get(), pre_paddings.size(), pre_paddings.data(),
295+
post_paddings.data(), padding_value, input_id, output_id, /*flags=*/0);
307296
EXPECT_EQ(status, xnn_status_success);
308297
return *this;
309298
}

test/subgraph/subgraph-tester.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,6 @@ class SubgraphTester {
361361
SubgraphTester& AddConcatenate(size_t axis, std::vector<uint32_t> input_ids,
362362
uint32_t output_id);
363363

364-
SubgraphTester& AddConstantPad(const size_t* pre_paddings,
365-
const size_t* post_paddings,
366-
float padding_value, uint32_t input_id,
367-
uint32_t output_id);
368-
369364
SubgraphTester& AddConstantPad(const std::vector<size_t>& pre_paddings,
370365
const std::vector<size_t>& post_paddings,
371366
float padding_value, uint32_t input_id,

0 commit comments

Comments
 (0)