From 7b55fb7e1c004581bf6dd32e47868f13c0127933 Mon Sep 17 00:00:00 2001 From: Jaeyun Jung Date: Fri, 19 May 2023 16:17:18 +0900 Subject: [PATCH] [Common] prepare 0-init dimension Prepare increasing max rank and 0-init dimension case. Signed-off-by: Jaeyun Jung --- .../tensor_filter/tensor_filter_tensorflow_lite.cc | 14 ++- .../include/nnstreamer_plugin_api_util.h | 10 +- gst/nnstreamer/nnstreamer_plugin_api_util_impl.c | 102 +++++++++++++++------ .../tensor_filter/tensor_filter_common.c | 2 +- tests/common/unittest_common.cc | 2 +- 5 files changed, 96 insertions(+), 34 deletions(-) diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc b/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc index 0c2e4b2..6fb311c 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc +++ b/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc @@ -626,12 +626,18 @@ TFLiteInterpreter::getTensorDim (int tensor_idx, tensor_dim dim) { TfLiteIntArray *tensor_dims = interpreter->tensor (tensor_idx)->dims; int len = tensor_dims->size; + + /* 0-init */ + for (guint i = 0; i < NNS_TENSOR_RANK_LIMIT; ++i) + dim[i] = 0; + if (len > NNS_TENSOR_RANK_LIMIT) return -EPERM; /* the order of dimension is reversed at CAPS negotiation */ std::reverse_copy (tensor_dims->data, tensor_dims->data + len, dim); + /** @todo remove below lines (dno not fill 1) */ /* fill the remnants with 1 */ for (int i = len; i < NNS_TENSOR_RANK_LIMIT; ++i) { dim[i] = 1; @@ -730,8 +736,12 @@ TFLiteInterpreter::setInputTensorsInfo (const GstTensorsInfo *info) * iterate over all possible ranks starting from MIN rank to the actual rank * of the dimension array. In case of none of these ranks work, return error */ - input_rank = gst_tensor_info_get_rank (tensor_info); - for (int rank = input_rank; rank <= NNS_TENSOR_RANK_LIMIT; rank++) { + for (input_rank = NNS_TENSOR_RANK_LIMIT - 1; input_rank > 0; input_rank--) { + if (tensor_info->dimension[input_rank] > 1) + break; + } + + for (int rank = input_rank + 1; rank <= NNS_TENSOR_RANK_LIMIT; rank++) { std::vector dims (rank); /* the order of dimension is reversed at CAPS negotiation */ for (int idx = 0; idx < rank; idx++) { diff --git a/gst/nnstreamer/include/nnstreamer_plugin_api_util.h b/gst/nnstreamer/include/nnstreamer_plugin_api_util.h index a25bc7a..a010b94 100644 --- a/gst/nnstreamer/include/nnstreamer_plugin_api_util.h +++ b/gst/nnstreamer/include/nnstreamer_plugin_api_util.h @@ -91,7 +91,7 @@ gst_tensor_info_convert_to_meta (GstTensorInfo * info, GstTensorMetaInfo * meta) * @param info tensor info structure * @return tensor rank (Minimum rank is 1 if given info is valid) */ -extern gint +extern guint gst_tensor_info_get_rank (const GstTensorInfo * info); /** @@ -290,6 +290,14 @@ extern gboolean gst_tensor_dimension_is_equal (const tensor_dim dim1, const tensor_dim dim2); /** + * @brief Get the rank of tensor dimension. + * @param dim tensor dimension. + * @return tensor rank (Minimum rank is 1 if given info is valid) + */ +extern guint +gst_tensor_dimension_get_rank (const tensor_dim dim); + +/** * @brief Parse tensor dimension parameter string * @return The Rank. 0 if error. * @param dimstr The dimension string in the format of d1:...:d8, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d8][d7][d6][d5][d4][d3][d2][d1]; diff --git a/gst/nnstreamer/nnstreamer_plugin_api_util_impl.c b/gst/nnstreamer/nnstreamer_plugin_api_util_impl.c index 8f89ac5..25f3577 100644 --- a/gst/nnstreamer/nnstreamer_plugin_api_util_impl.c +++ b/gst/nnstreamer/nnstreamer_plugin_api_util_impl.c @@ -208,12 +208,10 @@ gst_tensor_info_is_equal (const GstTensorInfo * i1, const GstTensorInfo * i2) } if (!gst_tensor_dimension_is_equal (i1->dimension, i2->dimension)) { - gchar *dim_str1 = gst_tensor_get_dimension_string (i1->dimension); - gchar *dim_str2 = gst_tensor_get_dimension_string (i2->dimension); + g_autofree gchar *_dim1 = gst_tensor_get_dimension_string (i1->dimension); + g_autofree gchar *_dim2 = gst_tensor_get_dimension_string (i2->dimension); nns_logd ("Tensor info is not equal. Given tensor dimensions %s vs %s", - dim_str1, dim_str2); - g_free (dim_str1); - g_free (dim_str2); + _dim1, _dim2); return FALSE; } @@ -286,7 +284,7 @@ gst_tensor_info_convert_to_meta (GstTensorInfo * info, GstTensorMetaInfo * meta) * @param info tensor info structure * @return tensor rank (Minimum rank is 1 if given info is valid) */ -gint +guint gst_tensor_info_get_rank (const GstTensorInfo * info) { gint idx; @@ -298,7 +296,7 @@ gst_tensor_info_get_rank (const GstTensorInfo * info) if (info->dimension[idx] != 1) break; } - + /** @todo use gst_tensor_dimension_get_rank (info->dimension) after 0-init dim is done */ return idx + 1; } @@ -987,22 +985,28 @@ gboolean gst_tensor_dimension_is_valid (const tensor_dim dim) { guint i; + gboolean is_valid = FALSE; - for (i = 0; i < NNS_TENSOR_RANK_LIMIT; ++i) { - if (dim[i] == 0) { - gchar *dim_str = gst_tensor_get_dimension_string (dim); - nns_logd - ("Failed to validate tensor dimension. Given dimension: %s. The dimension string should be in the form of d1:...:d8, d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1. Here, dN is a positive integer.", - dim_str); - _nnstreamer_error_write - ("Failed to validate tensor dimension. Given dimension: %s. The dimension string should be in the form of d1:...:d8, d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1. Here, dN is a positive integer.", - dim_str); - g_free (dim_str); - return FALSE; - } + i = gst_tensor_dimension_get_rank (dim); + if (i == 0) + goto done; + + for (; i < NNS_TENSOR_RANK_LIMIT; i++) { + if (dim[i] > 0) + goto done; } - return TRUE; + is_valid = TRUE; + +done: + if (!is_valid) { + nns_logd + ("Failed to validate tensor dimension. The dimension string should be in the form of d1:...:d8, d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1. Here, dN is a positive integer."); + _nnstreamer_error_write + ("Failed to validate tensor dimension. The dimension string should be in the form of d1:...:d8, d1:d2:d3:d4, d1:d2:d3, d1:d2, or d1. Here, dN is a positive integer."); + } + + return is_valid; } /** @@ -1019,14 +1023,46 @@ gst_tensor_dimension_is_equal (const tensor_dim dim1, const tensor_dim dim2) return FALSE; for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) { - if (dim1[i] != dim2[i]) - return FALSE; + if (dim1[i] != dim2[i]) { + const tensor_dim *remained; + + if (dim1[i] == 0U) + remained = (const tensor_dim *) &dim2; + else if (dim2[i] == 0U) + remained = (const tensor_dim *) &dim1; + else + return FALSE; + + /* Supposed dimension is same if remained dimension is 1. */ + for (; i < NNS_TENSOR_RANK_LIMIT; i++) { + if ((*remained)[i] > 1) + return FALSE; + } + } } return TRUE; } /** + * @brief Get the rank of tensor dimension. + * @param dim tensor dimension. + * @return tensor rank (Minimum rank is 1 if given dimension is valid) + */ +guint +gst_tensor_dimension_get_rank (const tensor_dim dim) +{ + guint i; + + for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) { + if (dim[i] == 0) + break; + } + + return i; +} + +/** * @brief Parse tensor dimension parameter string * @return The Rank. 0 if error. * @param dimstr The dimension string in the format of d1:...:d8, d1:d2:d3, d1:d2, or d1, where dN is a positive integer and d1 is the innermost dimension; i.e., dim[d8][d7][d6][d5][d4][d3][d2][d1]; @@ -1065,6 +1101,10 @@ gst_tensor_parse_dimension (const gchar * dimstr, tensor_dim dim) rank = i + 1; } + /** + * @todo remove below lines + * (0-initialized before parsing the string, filled remained dimension with 0) + */ for (; i < NNS_TENSOR_RANK_LIMIT; i++) dim[i] = 1; @@ -1109,9 +1149,12 @@ gst_tensor_get_rank_dimension_string (const tensor_dim dim, actual_rank = rank; for (i = 0; i < actual_rank; i++) { + if (dim[i] == 0) + break; + g_string_append_printf (dim_str, "%u", dim[i]); - if (i < actual_rank - 1) { + if (i < actual_rank - 1 && dim[i + 1] > 0) { g_string_append (dim_str, ":"); } } @@ -1149,10 +1192,8 @@ gst_tensor_dimension_string_is_equal (const gchar * dimstr1, rank1 = gst_tensor_parse_dimension (strv1[i], dim1); rank2 = gst_tensor_parse_dimension (strv2[i], dim2); - if (!rank1 || !rank2) - goto done; - - if (!gst_tensor_dimension_is_equal (dim1, dim2)) + /* 'rank 0' means invalid dimension */ + if (!rank1 || !rank2 || !gst_tensor_dimension_is_equal (dim1, dim2)) goto done; } @@ -1178,10 +1219,13 @@ gst_tensor_get_element_count (const tensor_dim dim) guint i; for (i = 0; i < NNS_TENSOR_RANK_LIMIT; i++) { + if (dim[i] == 0) + break; + count *= dim[i]; } - return count; + return (i > 0) ? count : 0; } /** @@ -1559,7 +1603,7 @@ gst_tensor_meta_info_convert (GstTensorMetaInfo * meta, GstTensorInfo * info) break; } - /** @todo handle rank from info.dimension */ + /** @todo handle rank from info.dimension (Fill 0, not 1) */ info->dimension[i] = (meta->dimension[i] > 0) ? meta->dimension[i] : 1; } diff --git a/gst/nnstreamer/tensor_filter/tensor_filter_common.c b/gst/nnstreamer/tensor_filter/tensor_filter_common.c index afffd4a..8061e5f 100644 --- a/gst/nnstreamer/tensor_filter/tensor_filter_common.c +++ b/gst/nnstreamer/tensor_filter/tensor_filter_common.c @@ -263,7 +263,7 @@ gst_tensor_filter_get_rank_string (const GstTensorFilterProperties * prop, if (_ranks[i] != 0) g_string_append_printf (rank, "%u", _ranks[i]); else - g_string_append_printf (rank, "%d", + g_string_append_printf (rank, "%u", gst_tensor_info_get_rank (&_meta->info[i])); if (i < _meta->num_tensors - 1) diff --git a/tests/common/unittest_common.cc b/tests/common/unittest_common.cc index 9ce776f..5770e79 100644 --- a/tests/common/unittest_common.cc +++ b/tests/common/unittest_common.cc @@ -767,7 +767,7 @@ TEST (commonTensorsInfo, equalInvalidParam1_n) */ TEST (commonTensorInfo, getrankInvalidParam0_n) { - EXPECT_EQ (0, gst_tensor_info_get_rank (NULL)); + EXPECT_EQ (0U, gst_tensor_info_get_rank (NULL)); } /** -- 2.7.4