[tf2tflite-dredd-pb-test] Introducing tf2tflite-dredd-pb-test (#8779)
author윤현식/On-Device Lab(SR)/Principal Engineer/삼성전자 <hyunsik.yoon@samsung.com>
Wed, 6 Nov 2019 09:18:43 +0000 (18:18 +0900)
committer박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Wed, 6 Nov 2019 09:18:43 +0000 (18:18 +0900)
* [tf2tflite-dredd-pb-test] Introducing tf2tflite-dredd-pb-test

This adds tf2tflite-dredd-pb-test, which tests tflite file to check if optimization is done right, etc.

Signed-off-by: Hyun Sik Yoon <hyunsik.yoon@samsung.com>
* remove tfkit

* remove downloading feature

* file existence checking macro

* remove tfkit again

* revising check_file_exist

compiler/tf2tflite-dredd-pb-test/.gitignore [new file with mode: 0644]
compiler/tf2tflite-dredd-pb-test/CMakeLists.txt [new file with mode: 0644]
compiler/tf2tflite-dredd-pb-test/contrib/.gitignore [new file with mode: 0644]
compiler/tf2tflite-dredd-pb-test/requires.cmake [new file with mode: 0644]
compiler/tf2tflite-dredd-pb-test/rule-lib.sh [new file with mode: 0755]
compiler/tf2tflite-dredd-pb-test/runner.sh [new file with mode: 0755]

diff --git a/compiler/tf2tflite-dredd-pb-test/.gitignore b/compiler/tf2tflite-dredd-pb-test/.gitignore
new file mode 100644 (file)
index 0000000..23c7c1b
--- /dev/null
@@ -0,0 +1 @@
+/contrib.lst
diff --git a/compiler/tf2tflite-dredd-pb-test/CMakeLists.txt b/compiler/tf2tflite-dredd-pb-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b636d7b
--- /dev/null
@@ -0,0 +1,135 @@
+nnas_include(TargetRequire)
+
+unset(REQUIRED_TARGETS)
+list(APPEND REQUIRED_TARGETS tfl-inspect)
+list(APPEND REQUIRED_TARGETS tf2tflite)
+TargetRequire_Return(${REQUIRED_TARGETS})
+
+nncc_find_resource(TensorFlowTests)
+
+set(PB_MODEL_REPO "${CMAKE_CURRENT_SOURCE_DIR}/contrib") # Where to find models to test
+
+unset(KEYS)
+unset(DEPS)
+
+function(check_file_exist)
+
+  foreach(FILE_PATH IN LISTS ARGV)
+    if(NOT EXISTS "${FILE_PATH}")
+      message(FATAL_ERROR "${FILE_PATH} does not exist." )
+    endif()
+  endforeach()
+
+endfunction()
+
+#
+# processing models in contrib.lst
+#
+# Example)
+#
+#  Add(Inception_v3 RULE test.rule)
+#    -> Read compiler/tf2tflite-dredd-pb-test/contrib/Inception_v3/test.pb and generate
+#      "Inception_v3.tflite". Then rule file is tested for the generated tflite file.
+#
+macro(Add MODEL_DIR)
+
+  set(ARG_OPTION)
+  set(ARG_ONE_VALUE RULE) # rule file name
+  set(ARG_MULTI_VALUE)
+  cmake_parse_arguments(ARG "${ARG_OPTION}" "${ARG_ONE_VALUE}" "${ARG_MULTI_VALUE}" ${ARGN})
+
+  if(NOT ARG_RULE )
+    message( FATAL_ERROR "RULE is mandadatory arg" )
+  endif()
+
+  set(RULE_FILENAME ${ARG_RULE})
+
+  set(MODEL_SOURCE_DIR "${PB_MODEL_REPO}/${MODEL_DIR}")
+
+  set(PB_PATH "${MODEL_SOURCE_DIR}/test.pb")
+  set(INFO_PATH "${MODEL_SOURCE_DIR}/test.info")
+  set(RULE_PATH "${MODEL_SOURCE_DIR}/${RULE_FILENAME}")
+
+  check_file_exist(${PB_PATH} ${INFO_PATH} ${RULE_PATH})
+
+  # Generate .test file which declares path of target pb, info, rule files
+  set(TARGET_TESTNAME "${MODEL_DIR}")
+  set(TEST_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_TESTNAME}.test")
+
+  add_custom_command(
+    OUTPUT ${TEST_CONFIG_FILE}
+    COMMAND ${CMAKE_COMMAND} -E remove -f ${TEST_CONFIG_FILE}
+    COMMAND ${CMAKE_COMMAND} -E echo 'MODEL_PB_PATH="${PB_PATH}"' >> ${TEST_CONFIG_FILE}
+    COMMAND ${CMAKE_COMMAND} -E echo 'MODEL_INFO_PATH="${INFO_PATH}"' >> ${TEST_CONFIG_FILE}
+    COMMAND ${CMAKE_COMMAND} -E echo 'MODEL_RULE_PATH="${RULE_PATH}"' >> ${TEST_CONFIG_FILE}
+    DEPENDS
+      ${PB_PATH}
+    COMMENT "Generate ${TARGET_TESTNAME} configuration for BIN"
+  )
+
+  list(APPEND KEYS "${TARGET_TESTNAME}")
+  list(APPEND DEPS "${TEST_CONFIG_FILE}")
+
+endmacro(Add)
+
+include(contrib.lst OPTIONAL)
+
+#
+# Generate toolchain.config
+#
+set(TOOLCHAIN_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/toolchain.config")
+
+add_custom_command(
+  OUTPUT ${TOOLCHAIN_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E remove -f ${TOOLCHAIN_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'TFL_INSPECT_PATH=\"$<TARGET_FILE:tfl-inspect>\"' >> ${TOOLCHAIN_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'TF2TFLITE_PATH=\"$<TARGET_FILE:tf2tflite>\"' >> ${TOOLCHAIN_CONFIG}
+  # add more if new excutable file is needed in runner.sh and rule-lib.sh
+  DEPENDS
+    tfl-inspect
+    tf2tflite
+  COMMENT "Generate toolchin configuration"
+)
+
+list(APPEND DEPS "${TOOLCHAIN_CONFIG}")
+
+#
+# Generate quality test runner
+#
+set(SOURCE_RUNNER "${CMAKE_CURRENT_SOURCE_DIR}/runner.sh")
+set(TARGET_RUNNER "${CMAKE_CURRENT_BINARY_DIR}/runner.sh")
+
+add_custom_command(
+  OUTPUT ${TARGET_RUNNER}
+  COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE_RUNNER}" "${TARGET_RUNNER}"
+  DEPENDS ${SOURCE_RUNNER}
+  COMMENT "Generate test runner"
+)
+
+list(APPEND DEPS "${TARGET_RUNNER}")
+
+#
+# Generate rule-lib
+#
+set(SOURCE_RULE_LIB "${CMAKE_CURRENT_SOURCE_DIR}/rule-lib.sh")
+set(TARGET_RULE_LIB "${CMAKE_CURRENT_BINARY_DIR}/rule-lib.sh")
+
+add_custom_command(
+  OUTPUT ${TARGET_RULE_LIB}
+  COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE_RULE_LIB}" "${TARGET_RULE_LIB}"
+  DEPENDS ${SOURCE_RULE_LIB}
+  COMMENT "Generate rule lib"
+)
+
+list(APPEND DEPS "${TARGET_RULE_LIB}")
+
+# Generate dependencies
+add_custom_target(tf2tflite_dredd_pb_deps ALL DEPENDS ${DEPS})
+
+add_test(
+  NAME tf2tflite_dredd_pb_test
+  COMMAND
+    "${TARGET_RUNNER}"
+    "${TOOLCHAIN_CONFIG}"
+    ${KEYS}
+)
diff --git a/compiler/tf2tflite-dredd-pb-test/contrib/.gitignore b/compiler/tf2tflite-dredd-pb-test/contrib/.gitignore
new file mode 100644 (file)
index 0000000..968c345
--- /dev/null
@@ -0,0 +1,3 @@
+/*
+# Exclude all except below
+!.gitignore
diff --git a/compiler/tf2tflite-dredd-pb-test/requires.cmake b/compiler/tf2tflite-dredd-pb-test/requires.cmake
new file mode 100644 (file)
index 0000000..4b3d089
--- /dev/null
@@ -0,0 +1,2 @@
+require("tf2tflite")
+require("tfl-inspect")
diff --git a/compiler/tf2tflite-dredd-pb-test/rule-lib.sh b/compiler/tf2tflite-dredd-pb-test/rule-lib.sh
new file mode 100755 (executable)
index 0000000..5f4856b
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/bash
+
+ERROR_FLAG="Error"
+
+#
+# Define rule
+#
+#   - Params: rule name (metric), actual value, condition, expected value
+#     - condition is '=', '!=', '<', '>', '<=', '>='. Refer to "man expr"
+#   - Return
+#     - 0 : success
+#     - 1 : fail (condition check fail)
+#     - 10 : error while getting actual value
+#     - 11 : error while running expected value
+#     - 20 : wrong param count
+#
+
+RULE()
+{
+  if [ "$#" -ne 4 ];then
+    echo "** [Error] count of RULE parameter should be 4"
+    return 20
+  fi
+
+  RULE_NAME=$1
+  ACTUAL=$2
+  COND=$3
+  EXPECTED=$4
+
+  # not to exit when expr result with 0
+  set +e
+
+  # check if ACTUAL or EXPECTED has "ERROR" string
+  expr match "${ACTUAL}" ${ERROR_FLAG}
+  if [ $? = 0 ]; then
+    echo "** Error in ACTUAL"
+    return 10
+  fi
+
+  expr match "${EXPECTED}" ${ERROR_FLAG}
+  if [ $? = 0 ]; then
+    echo "** Error in EXPECTED"
+    return 11
+  fi
+
+  expr ${ACTUAL} ${COND} ${EXPECTED}
+  RESULT=$?
+
+  # roll-back
+  set -e
+
+  # Note: return value of 'expr'
+  # - 0 : result is true
+  # - 1 : result is not false
+  # - 2 : error
+
+  if [ ${RESULT} -eq 0 ];then
+    echo -e "\n** [${RULE_NAME}] \t success \t ([actual: ${ACTUAL}] ${COND} [expected: ${EXPECTED}])\n"
+  elif [ ${RESULT} -eq 1 ];then
+    echo -e "\n** [${RULE_NAME}] \t ** fail \t ([actual: ${ACTUAL}] ${COND} [expected: ${EXPECTED}])\n"
+  else
+    echo -e "\t** Error in [expr ${ACTUAL} ${COND} ${EXPECTED}]"
+  fi
+
+  return ${RESULT}
+}
+
+#
+# Define each function to get quality value
+#
+
+# Note: These function is called by a sub-shell.
+# So return value should be passed through "echo return_value"
+# tip: for debugging, surround the code with "set -x" and "set +x"
+
+file_size()
+{
+  if [ ! -f ${TFLITE_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFLITE_PATH} does not exist"
+  else
+    echo `cat ${TFLITE_PATH} | wc -c`
+  fi
+}
+
+all_op_count()
+{
+  if [ ! -f ${TFLITE_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFLITE_PATH} does not exist"
+  elif [ ! -f ${TFL_INSPECT_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFL_INSPECT_PATH} does not exist"
+  else
+    echo `${TFL_INSPECT_PATH} --operators ${TFLITE_PATH} | wc -l`
+  fi
+}
+
+op_count()
+{
+  if [ "$#" -ne 1 ];then
+    echo "${ERROR_FLAG} - Wrong argument number"
+  elif [ ! -f ${TFLITE_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFLITE_PATH} does not exist"
+  elif [ ! -f ${TFL_INSPECT_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFL_INSPECT_PATH} does not exist"
+  else
+    echo `${TFL_INSPECT_PATH} --operators ${TFLITE_PATH} | grep -w "$1" | wc -l`
+  fi
+}
+
+conv2d_weight_not_constant()
+{
+  if [ ! -f ${TFLITE_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFLITE_PATH} does not exist"
+  elif [ ! -f ${TFL_INSPECT_PATH} ]; then
+    echo "${ERROR_FLAG} - ${TFL_INSPECT_PATH} does not exist"
+  else
+    echo `${TFL_INSPECT_PATH} --conv2d_weight ${TFLITE_PATH} | awk -F, '{ if ($2 != "CONST") print $0}' | wc -l`
+  fi
+}
+
+# TODO define more qullity test function
diff --git a/compiler/tf2tflite-dredd-pb-test/runner.sh b/compiler/tf2tflite-dredd-pb-test/runner.sh
new file mode 100755 (executable)
index 0000000..f84137e
--- /dev/null
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+# This script checks tflite file generated by tf2tflite
+
+WORKDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+
+# Need at least toolchain.config
+if [[ $# -lt 1 ]]; then
+  echo "USAGE: $0 ..."
+  echo
+  echo "ARGUMENTS:"
+  echo "  [toolchain.config path]"
+  echo "  [Prefix1]"
+  echo "  [Prefix2]"
+  echo "  ..."
+  exit 255
+fi
+
+CONFIG_PATH="$1"; shift
+
+source "${CONFIG_PATH}"
+
+echo "-- Found tfl-inspect: ${TFL_INSPECT_PATH}"
+echo "-- Found tf2tflite: ${TF2TFLITE_PATH}"
+echo "-- Found workdir: ${WORKDIR}"
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+pushd "${WORKDIR}"
+
+# loading RULE and functions that checks tflite file
+source rule-lib.sh
+
+while [[ $# -ne 0 ]]; do
+  PREFIX="$1"; shift
+
+  echo "[ RUN      ] ${PREFIX}"
+
+  TESTED+=("${PREFIX}")
+
+  PASSED_TAG="${PREFIX}.passed"
+
+  rm -f "${PASSED_TAG}"
+
+  cat > "${PREFIX}.log" <(
+    exec 2>&1
+
+    source "${PREFIX}.test"
+
+    echo "-- Use '${MODEL_PB_PATH}', '${MODEL_INFO_PATH}', and '${MODEL_RULE_PATH}'"
+
+    # Exit immediately if any command fails
+    set -e
+    # Show commands
+    set -x
+
+    # Generate tflite
+    "${TF2TFLITE_PATH}" \
+      "${MODEL_INFO_PATH}" \
+      "${MODEL_PB_PATH}" \
+      "${WORKDIR}/${PREFIX}.tflite"
+
+    #
+    # Run rule prepared to check tflite file
+    #
+
+    # set vars needed by rule file
+    TFLITE_PATH="${WORKDIR}/${PREFIX}.tflite"
+
+    # Note: turn off 'command printing'. Otherwise printing will be so messy
+    set +x
+    source "${MODEL_RULE_PATH}"
+    set -x
+
+    if [[ $? -eq 0 ]]; then
+      touch "${PASSED_TAG}"
+    fi
+  )
+
+  if [[ -f "${PASSED_TAG}" ]]; then
+    echo "[       OK ] ${PREFIX}"
+    PASSED+=("$PREFIX")
+  else
+    echo "[      FAIL] ${PREFIX}"
+    FAILED+=("$PREFIX")
+  fi
+done
+popd
+
+if [[ ${#TESTED[@]} -ne ${#PASSED[@]} ]]; then
+  echo "FAILED"
+  for TEST in "${FAILED[@]}"
+  do
+    echo "- ${TEST}"
+  done
+  exit 255
+fi
+
+echo "PASSED"
+exit 0