From 30d8a6224cbc711cfd62a2072534312d2efc52bd Mon Sep 17 00:00:00 2001 From: Parichay Kapoor Date: Mon, 16 Dec 2019 11:24:29 +0900 Subject: [PATCH] [nnfw] Set accelerator for nnfw Allow setting of accelerator for nnfw Parsing accelerator moved to tensor_filter_common. Currently, used in tflite and nnfw, and use directly for other filters like this. V2: Added note that PROP_ACCELERATOR is supported in a few filter extensions only. Signed-off-by: Parichay Kapoor --- ext/nnstreamer/tensor_filter/tensor_filter_nnfw.c | 59 ++++++++++++++++++++-- .../tensor_filter/tensor_filter_tensorflow_lite.cc | 38 +++----------- gst/nnstreamer/nnstreamer_plugin_api_filter.h | 7 +++ .../tensor_filter/tensor_filter_common.c | 51 ++++++++++++++++++- 4 files changed, 118 insertions(+), 37 deletions(-) diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_nnfw.c b/ext/nnstreamer/tensor_filter/tensor_filter_nnfw.c index c05e716..ebc0b08 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_nnfw.c +++ b/ext/nnstreamer/tensor_filter/tensor_filter_nnfw.c @@ -44,6 +44,26 @@ #define NNFW_SRCN_BACKEND "srcn" #define NNFW_DEFAULT_BACKEND NNFW_CPU_BACKEND +/** Match all accelerators for nnapi at once */ +#define REGEX_ACCL_NNFW \ + "(^(true)[:]?([(]?(" \ + REGEX_ACCL_AUTO "|" \ + REGEX_ACCL_DEF "|" \ + REGEX_ACCL_CPU "|" \ + REGEX_ACCL_GPU "|" \ + REGEX_ACCL_SRCN "|" \ + REGEX_ACCL_NEON ")*[)]?))" + +/** Match accelerator for nnapi one by one */ +#define REGEX_ACCL_NNFW_ELEM \ + "(" \ + "(?accelerator = parse_accl_hw (accelerators, REGEX_ACCL_NNFW, + REGEX_ACCL_NNFW_ELEM); + + switch (pdata->accelerator) { + case ACCL_SRCN: + return NNFW_SRCN_BACKEND; + case ACCL_NEON: + return NNFW_NEON_BACKEND; + case ACCL_GPU: + return NNFW_GPU_BACKEND; + case ACCL_CPU: + return NNFW_CPU_BACKEND; + case ACCL_DEFAULT: + /** intended */ + default: + return NNFW_DEFAULT_BACKEND; + } +} + +/** * @brief The standard tensor_filter callback */ static int @@ -72,6 +121,7 @@ nnfw_open (const GstTensorFilterProperties * prop, void **private_data) nnfw_pdata *pdata; char *model_path = NULL; char *meta_file = NULL; + const char *accelerator = NULL; if (*private_data != NULL) { pdata = *private_data; @@ -95,15 +145,14 @@ nnfw_open (const GstTensorFilterProperties * prop, void **private_data) goto unalloc_exit; } - /** - * @todo: remove after fixes to nnfw package for aarch64 - */ - status = nnfw_set_available_backends(pdata->session, NNFW_DEFAULT_BACKEND); + accelerator = nnfw_get_accelerator (pdata, prop->accl_str); + status = nnfw_set_available_backends(pdata->session, accelerator); if (status != NNFW_STATUS_NO_ERROR) { err = -EINVAL; - g_printerr ("Cannot set nnfw-runtime backend to %s", NNFW_DEFAULT_BACKEND); + g_printerr ("Cannot set nnfw-runtime backend to %s", accelerator); goto unalloc_exit; } + /** @note nnfw opens the first model listed in the MANIFEST file */ model_path = g_path_get_dirname (prop->model_files[0]); meta_file = g_build_filename (model_path, "metadata", "MANIFEST", NULL); diff --git a/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc b/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc index a7d495d..5338f5b 100644 --- a/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc +++ b/ext/nnstreamer/tensor_filter/tensor_filter_tensorflow_lite.cc @@ -525,40 +525,16 @@ TFLiteCore::TFLiteCore (const char * _model_path, const char * accelerators) #endif } +/** + * @brief Set the accelerator for the tf engine + */ void TFLiteCore::setAccelerator (const char * accelerators) { - GRegex * nnapi_elem; - GMatchInfo * match_info; - - if (accelerators == NULL) { - goto use_nnapi_ini; - } - - /* If set by user, get the precise accelerator */ - use_nnapi = (bool) g_regex_match_simple (REGEX_ACCL_NNAPI, accelerators, - G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY); - if (use_nnapi == TRUE) { - /** Default to auto mode */ - accelerator = ACCL_AUTO; - nnapi_elem = g_regex_new (REGEX_ACCL_NNAPI_ELEM, G_REGEX_CASELESS, - G_REGEX_MATCH_NOTEMPTY, NULL); - - /** Now match each provided element and get specific accelerator */ - if (g_regex_match (nnapi_elem, accelerators, G_REGEX_MATCH_NOTEMPTY, - &match_info)) { - - while (g_match_info_matches (match_info)) { - gchar *word = g_match_info_fetch (match_info, 0); - accelerator = get_accl_hw_type (word); - g_free (word); - break; - } - } - g_match_info_free (match_info); - g_regex_unref (nnapi_elem); - } else { + use_nnapi = TRUE; + accelerator = parse_accl_hw (accelerators, REGEX_ACCL_NNAPI, + REGEX_ACCL_NNAPI_ELEM); + if (accelerators == NULL || accelerator == ACCL_NONE) goto use_nnapi_ini; - } return; diff --git a/gst/nnstreamer/nnstreamer_plugin_api_filter.h b/gst/nnstreamer/nnstreamer_plugin_api_filter.h index ae7e3bd..b3dceb8 100644 --- a/gst/nnstreamer/nnstreamer_plugin_api_filter.h +++ b/gst/nnstreamer/nnstreamer_plugin_api_filter.h @@ -248,6 +248,13 @@ get_accl_hw_type (const char * str); extern const char * get_accl_hw_str (const accl_hw key); +/** + * @brief parse user given string to extract accelerator based on given regex + */ +extern accl_hw +parse_accl_hw (const char * accelerators, const char * regex_accl, + const char * regex_accl_elem); + #ifdef __cplusplus } #endif diff --git a/gst/nnstreamer/tensor_filter/tensor_filter_common.c b/gst/nnstreamer/tensor_filter/tensor_filter_common.c index 8a6ac45..932be51 100644 --- a/gst/nnstreamer/tensor_filter/tensor_filter_common.c +++ b/gst/nnstreamer/tensor_filter/tensor_filter_common.c @@ -268,7 +268,8 @@ gst_tensor_filter_install_properties (GObjectClass * gobject_class) "(true/false):(comma separated ACCELERATOR(s)). " "true/false determines if accelerator is to be used. " "list of accelerators determines the backend (ignored with false). " - "Example, if GPU, NPU can be used but not CPU - true:(GPU,NPU,!CPU).", + "Example, if GPU, NPU can be used but not CPU - true:(GPU,NPU,!CPU). " + "Note that only a few subplugins support this property.", "", G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_IS_UPDATABLE, g_param_spec_boolean ("is-updatable", "Updatable model", @@ -821,3 +822,51 @@ get_accl_hw_str (const accl_hw key) return ACCL_NONE_STR; } } + +/** + * @brief parse user given string to extract accelerator based on given regex + * @param[in] accelerators user given input + * @param[in] regex_accl regex to determine if accelerator or not + * @param[in] regex_accl_elem regex to determine which accelerator + * @return Corresponding string. Returns ACCL_NONE_STR if not found. + */ +accl_hw +parse_accl_hw (const gchar * accelerators, const gchar * regex_accl, + const gchar * regex_accl_elem) +{ + GRegex *nnapi_elem; + GMatchInfo *match_info; + gboolean use_accl; + accl_hw accl; + + if (accelerators == NULL) + return ACCL_DEFAULT; + + /* If set by user, get the precise accelerator */ + use_accl = (gboolean) g_regex_match_simple (regex_accl, accelerators, + G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY); + if (use_accl == TRUE) { + /** Default to auto mode */ + accl = ACCL_AUTO; + nnapi_elem = g_regex_new (regex_accl_elem, G_REGEX_CASELESS, + G_REGEX_MATCH_NOTEMPTY, NULL); + + /** Now match each provided element and get specific accelerator */ + if (g_regex_match (nnapi_elem, accelerators, G_REGEX_MATCH_NOTEMPTY, + &match_info)) { + + while (g_match_info_matches (match_info)) { + gchar *word = g_match_info_fetch (match_info, 0); + accl = get_accl_hw_type (word); + g_free (word); + break; + } + } + g_match_info_free (match_info); + g_regex_unref (nnapi_elem); + } else { + return ACCL_NONE; + } + + return accl; +} -- 2.7.4