From c9722f79ce24a00d546053cb06179f8c81d473c5 Mon Sep 17 00:00:00 2001 From: Mark Charlebois Date: Tue, 10 Aug 2021 10:21:01 -0700 Subject: [PATCH] Add qti backend Co-authored-by: Mohit Mundhra Co-authored-by: Aasheesh Tiwari --- .bazelrc | 10 + Makefile | 5 + mobile_back_qti/BUILD | 12 +- mobile_back_qti/DLC/Makefile | 321 +++++++++++ mobile_back_qti/DLC/argmax-quant.json | 13 + mobile_back_qti/README.md | 96 ++++ mobile_back_qti/builddir.mk | 24 + mobile_back_qti/cpp/backend_qti/BUILD | 149 ++++++ mobile_back_qti/cpp/backend_qti/allocator.cc | 56 ++ mobile_back_qti/cpp/backend_qti/allocator.h | 177 +++++++ .../cpp/backend_qti/allocator_test.cc | 67 +++ mobile_back_qti/cpp/backend_qti/cpuctrl.cc | 177 +++++++ mobile_back_qti/cpp/backend_qti/cpuctrl.h | 37 ++ .../cpp/backend_qti/mlperf_helper.h | 66 +++ .../cpp/backend_qti/qti_backend_helper.cc | 493 +++++++++++++++++ .../cpp/backend_qti/qti_backend_helper.h | 80 +++ mobile_back_qti/cpp/backend_qti/qti_c.cc | 298 +++++++++++ .../cpp/backend_qti/qti_settings.h | 259 +++++++++ .../backend_qti/qti_tflite_test_settings.h | 203 +++++++ mobile_back_qti/cpp/backend_qti/rpcmem.cc | 63 +++ mobile_back_qti/cpp/backend_qti/rpcmem.h | 43 ++ mobile_back_qti/cpp/backend_qti/test.cc | 72 +++ mobile_back_qti/cpp/backend_qti/tflite_c.cc | 239 +++++++++ mobile_back_qti/cpp/backend_qti/tflite_c.h | 46 ++ mobile_back_qti/datasets/Makefile | 49 ++ mobile_back_qti/datasets/README.md | 7 + mobile_back_qti/datasets/ade20k/Makefile | 84 +++ .../ade20k/ade20k_calibration_files.txt | 500 ++++++++++++++++++ .../datasets/ade20k/resize_512_ade20k.py | 43 ++ .../ade20k/resize_512_ade20k_calibration.py | 47 ++ mobile_back_qti/datasets/coco/Makefile | 88 +++ .../datasets/coco/coco_cal_images_list.txt | 500 ++++++++++++++++++ mobile_back_qti/datasets/coco/convert.sh | 8 + .../datasets/coco/upscale_coco.patch | 11 + mobile_back_qti/datasets/coco/upscale_coco.py | 78 +++ mobile_back_qti/datasets/imagenet/Makefile | 86 +++ .../datasets/imagenet/Resize224.py | 32 ++ mobile_back_qti/datasets/jpg_to_raw.py | 45 ++ mobile_back_qti/docker.mk | 29 + .../docker/mlperf_mobiledet/Dockerfile | 18 + mobile_back_qti/qti_backend.mk | 3 +- mobile_back_qti/qti_backend_targets.mk | 37 ++ mobile_back_qti/third_party/BUILD.bazel | 18 + .../third_party/tf_grappler_cost.diff | 19 + mobile_back_qti/utils/check_size.sh | 21 + mobile_back_qti/utils/chunkdownload.py | 35 ++ mobile_back_qti/utils/get_results.sh | 31 ++ 47 files changed, 4787 insertions(+), 8 deletions(-) create mode 100644 mobile_back_qti/DLC/Makefile create mode 100644 mobile_back_qti/DLC/argmax-quant.json create mode 100644 mobile_back_qti/README.md create mode 100644 mobile_back_qti/builddir.mk create mode 100644 mobile_back_qti/cpp/backend_qti/BUILD create mode 100644 mobile_back_qti/cpp/backend_qti/allocator.cc create mode 100644 mobile_back_qti/cpp/backend_qti/allocator.h create mode 100644 mobile_back_qti/cpp/backend_qti/allocator_test.cc create mode 100644 mobile_back_qti/cpp/backend_qti/cpuctrl.cc create mode 100644 mobile_back_qti/cpp/backend_qti/cpuctrl.h create mode 100644 mobile_back_qti/cpp/backend_qti/mlperf_helper.h create mode 100644 mobile_back_qti/cpp/backend_qti/qti_backend_helper.cc create mode 100644 mobile_back_qti/cpp/backend_qti/qti_backend_helper.h create mode 100644 mobile_back_qti/cpp/backend_qti/qti_c.cc create mode 100644 mobile_back_qti/cpp/backend_qti/qti_settings.h create mode 100644 mobile_back_qti/cpp/backend_qti/qti_tflite_test_settings.h create mode 100644 mobile_back_qti/cpp/backend_qti/rpcmem.cc create mode 100644 mobile_back_qti/cpp/backend_qti/rpcmem.h create mode 100644 mobile_back_qti/cpp/backend_qti/test.cc create mode 100644 mobile_back_qti/cpp/backend_qti/tflite_c.cc create mode 100644 mobile_back_qti/cpp/backend_qti/tflite_c.h create mode 100644 mobile_back_qti/datasets/Makefile create mode 100644 mobile_back_qti/datasets/README.md create mode 100644 mobile_back_qti/datasets/ade20k/Makefile create mode 100644 mobile_back_qti/datasets/ade20k/ade20k_calibration_files.txt create mode 100755 mobile_back_qti/datasets/ade20k/resize_512_ade20k.py create mode 100755 mobile_back_qti/datasets/ade20k/resize_512_ade20k_calibration.py create mode 100644 mobile_back_qti/datasets/coco/Makefile create mode 100644 mobile_back_qti/datasets/coco/coco_cal_images_list.txt create mode 100644 mobile_back_qti/datasets/coco/convert.sh create mode 100644 mobile_back_qti/datasets/coco/upscale_coco.patch create mode 100644 mobile_back_qti/datasets/coco/upscale_coco.py create mode 100644 mobile_back_qti/datasets/imagenet/Makefile create mode 100644 mobile_back_qti/datasets/imagenet/Resize224.py create mode 100644 mobile_back_qti/datasets/jpg_to_raw.py create mode 100644 mobile_back_qti/docker.mk create mode 100644 mobile_back_qti/docker/mlperf_mobiledet/Dockerfile create mode 100644 mobile_back_qti/qti_backend_targets.mk create mode 100644 mobile_back_qti/third_party/BUILD.bazel create mode 100644 mobile_back_qti/third_party/tf_grappler_cost.diff create mode 100755 mobile_back_qti/utils/check_size.sh create mode 100644 mobile_back_qti/utils/chunkdownload.py create mode 100755 mobile_back_qti/utils/get_results.sh diff --git a/.bazelrc b/.bazelrc index 700a4773e..a60c66c23 100644 --- a/.bazelrc +++ b/.bazelrc @@ -20,3 +20,13 @@ build --host_cxxopt='--std=c++14' test --fat_apk_cpu=x86_64,arm64-v8a test --host_crosstool_top=@bazel_tools//tools/cpp:toolchain +#common --experimental_repo_remote_exec +build:linux --copt=-w + +build:asan --strip=never +build:asan --copt -fsanitize=address +build:asan --copt -DADDRESS_SANITIZER +build:asan --copt -O1 +build:asan --copt -g +build:asan --copt -fno-omit-frame-pointer +build:asan --linkopt -fsanitize=address diff --git a/Makefile b/Makefile index 5cd9acff0..ef83062ad 100644 --- a/Makefile +++ b/Makefile @@ -144,3 +144,8 @@ clean: @([ -d output/home/mlperf/cache ] && chmod -R +w output/home/mlperf/cache) || true @rm -rf output +ifeq (${WITH_QTI},1) + include mobile_back_qti/qti_backend_targets.mk +endif + + diff --git a/mobile_back_qti/BUILD b/mobile_back_qti/BUILD index c096261cd..066a8b6bc 100644 --- a/mobile_back_qti/BUILD +++ b/mobile_back_qti/BUILD @@ -53,12 +53,12 @@ cc_library( cc_library( name = "qtibackend", srcs = select({ - "//conditions:default": ["//mobile_back_qti/cpp/backend_mock_qti:libqtibackend.so"], - # TODO: Add proper handling for QTI devices - ":android_arm64": ["//mobile_back_qti/cpp/backend_mock_qti:libqtibackend.so"], - # ":android_arm64": [ - # "//mobile_back_qti/cpp/backend_qti:libqtibackend.so", - # ], + "//conditions:default": [ + "//mobile_back_qti/cpp/backend_mock_qti:libqtibackend.so" + ], + ":android_arm64": [ + "//mobile_back_qti/cpp/backend_qti:libqtibackend.so" + ], }), deps = select({ "//conditions:default": [], diff --git a/mobile_back_qti/DLC/Makefile b/mobile_back_qti/DLC/Makefile new file mode 100644 index 000000000..7d501068a --- /dev/null +++ b/mobile_back_qti/DLC/Makefile @@ -0,0 +1,321 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +# This file must be called from top level Makefile + +include ../builddir.mk + +all: ${BUILDDIR}/datasets.stamp sdm865-dlc sdm888-dlc + +.PHONY: sdm865-dlc sdm888-dlc dependencies gen-sdm865-dlc-info gen-sdm888-dlc-info clean + +include ../docker.mk + +DLCBUILDDIR=${BUILDDIR}/DLC +MODEL_BASE_PATH=${BUILDDIR}/mobile +MOBILENETEDGETPU_MODEL_PATH=${MODEL_BASE_PATH}/vision/mobilenet/models_and_code/checkpoints/float +DEEPLABV3QAT_MODEL_PATH=${MODEL_BASE_PATH}/vision/deeplab/models_and_code/checkpoints/quantize_aware_training + +sdm865-dlc: ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_hta.stamp \ + ${DLCBUILDDIR}/ssd_mobiledet_qat_hta.stamp \ + ${DLCBUILDDIR}/deeplabv3_hta.stamp + +sdm888-dlc: ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_htp.stamp \ + ${DLCBUILDDIR}/ssd_mobiledet_qat_htp.stamp \ + ${DLCBUILDDIR}/deeplabv3_htp.stamp \ + ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_htp_batched.stamp + +mobiledet: \ + ${DLCBUILDDIR}/ssd_mobiledet_qat_hta.stamp \ + ${DLCBUILDDIR}/ssd_mobiledet_qat_htp.stamp + +${BUILDDIR}/datasets.stamp: + @(cd ../datasets && make) + @touch $@ + +${BUILDDIR}/mobile/.stamp: + @curl -H "Authorization: token ${GITHUB_TOKEN}" -o ${BUILDDIR}/mobile.zip -L https://github.com/mlcommons/mobile/archive/mobiledet-export_inference_graph.zip + @cd ${BUILDDIR} && unzip mobile.zip + @mv mobile-mobiledet-export_inference_graph mobile + @touch $@ + +${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_float.dlc: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${BUILDDIR}/mobile/.stamp + @echo "Mobilenetedge TPU model conversion ...." + @echo "Float model" + @mkdir -p ${DLCBUILDDIR} + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${MOBILENETEDGETPU_MODEL_PATH}:/models \ + -v ${DLCBUILDDIR}:/output \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '/snpe_sdk/bin/x86_64-linux-clang/snpe-tensorflow-to-dlc \ + -i /models/frozen_graph_tf1x_transform.pb \ + -d input "1,224,224,3" --out_node "MobilenetEdgeTPU/Predictions/Softmax" \ + -o /output/mobilenet_edgetpu_224_1.0_float.dlc' + +${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_hta.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_float.dlc + @echo "Quantization of MobilenetEdgeTPU DLC for HTA" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/imagenet/imagenet_out:/imagenet-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "cd /imagenet-out && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/mobilenet_edgetpu_224_1.0_float.dlc \ + --input_list=/imagenet-out/imagenet_image_list.txt \ + --output_dlc=/output/mobilenet_edgetpu_224_1.0_hta.dlc \ + --enable_hta" + @echo "Mobilenetedge TPU model conversion completed" + @touch $@ + +${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_htp.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_float.dlc + @echo "Quantization of MobilenetEdgeTPU DLC for HTP" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/imagenet/imagenet_out:/imagenet-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "cd /imagenet-out && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/mobilenet_edgetpu_224_1.0_float.dlc \ + --input_list=/imagenet-out/imagenet_image_list.txt \ + --output_dlc=/output/mobilenet_edgetpu_224_1.0_htp.dlc \ + --enable_htp" + @echo "Mobilenetedge TPU model conversion completed" + @touch $@ + +${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_float_batched.dlc: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${BUILDDIR}/mobile/.stamp + @echo "Mobilenetedge TPU model conversion ...." + @echo "Batched Float model" + @mkdir -p ${DLCBUILDDIR} + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${MOBILENETEDGETPU_MODEL_PATH}:/models \ + -v ${DLCBUILDDIR}:/output \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '/snpe_sdk/bin/x86_64-linux-clang/snpe-tensorflow-to-dlc \ + -i /models/frozen_graph_tf1x_transform.pb \ + -d input "3,224,224,3" --out_node "MobilenetEdgeTPU/Predictions/Softmax" \ + -o /output/mobilenet_edgetpu_224_1.0_float_batched.dlc' + +${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_htp_batched.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${DLCBUILDDIR}/mobilenet_edgetpu_224_1.0_float_batched.dlc + @echo "Quantization of MobilenetEdgeTPU Batched DLC for HTP" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/imagenet/imagenet_out:/imagenet-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "cd /imagenet-out && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/mobilenet_edgetpu_224_1.0_float_batched.dlc \ + --input_list=/imagenet-out/imagenet_image_list.txt \ + --output_dlc=/output/mobilenet_edgetpu_224_1.0_htp_batched.dlc \ + --enable_htp" + @echo "Mobilenetedge TPU model conversion completed" + @touch $@ + +${DLCBUILDDIR}/ssd_mobiledet_qat.dlc: \ + ${BUILDDIR}/mobile/.stamp + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/dlc \ + -v ${BUILDDIR}/mobile/vision/mobiledet/uint8/export_inference_graph:/model \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '/snpe_sdk/bin/x86_64-linux-clang/snpe-tensorflow-to-dlc \ + -i model/frozen_inference_graph.pb \ + -d Preprocessor/map/TensorArrayStack/TensorArrayGatherV3 "1,320,320,3" \ + --out_node "detection_classes" \ + --out_node "detection_boxes" \ + --out_node "detection_scores" \ + -o /dlc/ssd_mobiledet_qat.dlc' + +${DLCBUILDDIR}/ssd_mobiledet_qat_hta.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${BUILDDIR}/mobile/.stamp \ + ${DLCBUILDDIR}/ssd_mobiledet_qat.dlc + @echo "Quantization of MobileDET SSD DLC for HTA" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/coco/coco_out:/coco-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + bash -c "cd /coco-out && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/ssd_mobiledet_qat.dlc \ + --input_list=/coco-out/coco_image_list.txt \ + --output_dlc=/output/ssd_mobiledet_qat_hta.dlc \ + --enable_hta --hta_partitions sm8250" + @echo "SSD MobileDET model conversion for HTA completed" + @touch $@ + +${DLCBUILDDIR}/ssd_mobiledet_qat_htp.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${BUILDDIR}/mobile/.stamp \ + ${DLCBUILDDIR}/ssd_mobiledet_qat.dlc + @echo "Quantization of MobileDET SSD DLC for HTP" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${MOBILEDETSSDQAT_MODEL_PATH}:/models \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/coco/coco_out:/coco-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + bash -c "cd /coco-out && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/ssd_mobiledet_qat.dlc \ + --input_list=/coco-out/coco_image_list.txt \ + --output_dlc=/output/ssd_mobiledet_qat_htp.dlc \ + --enable_htp" + @echo "SSD MobileDET model conversion for HTP completed" + @touch $@ + + +${DLCBUILDDIR}/deeplabv3_quantized.dlc: ${TOPDIR}/DLC/argmax-quant.json ${DEEPLABV3QAT_MODEL_PATH}/freeze.pb \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${BUILDDIR}/mobile/.stamp + @echo "Deeplab v3 model conversion ...." + @echo "Deeplabv3 QAT model" + @cat ${TOPDIR}/DLC/argmax-quant.json + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DEEPLABV3QAT_MODEL_PATH}:/deeplabv3 \ + -v ${DLCBUILDDIR}:/output \ + -v ${TOPDIR}/DLC:/dlc \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '/snpe_sdk/bin/x86_64-linux-clang/snpe-tensorflow-to-dlc \ + -i /deeplabv3/freeze.pb \ + -d ImageTensor "1,512,512,3" \ + --out_node ArgMax \ + --quantization_overrides /dlc/argmax-quant.json \ + -o /output/deeplabv3_quantized.dlc' + @echo "Generated DLC from Deeplabv3 QAT model" + + +${DLCBUILDDIR}/deeplabv3_hta.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${DLCBUILDDIR}/deeplabv3_quantized.dlc + @echo "Quantization of Deeplabv3 DLC" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/ade20k/ade20k_out:/ade20k-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c 'cd /ade20k-out/ && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/deeplabv3_quantized.dlc \ + --input_list=/ade20k-out/ade20k_image_list.txt \ + --output_dlc=/output/deeplabv3_hta.dlc \ + --enable_hta' + @echo "Deeplab v3 model conversion completed" + @# Can't use deeplabv3_hta.dlc as make target since this file is present on failure + @touch $@ + +${DLCBUILDDIR}/deeplabv3_htp.stamp: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + ${DLCBUILDDIR}/deeplabv3_quantized.dlc + @echo "Quantization of Deeplabv3 DLC" + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/output \ + -v ${BUILDDIR}/ade20k/ade20k_out:/ade20k-out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c 'cd /ade20k-out/ && /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-quantize \ + --input_dlc=/output/deeplabv3_quantized.dlc \ + --input_list=/ade20k-out/ade20k_image_list.txt \ + --output_dlc=/output/deeplabv3_htp.dlc \ + --override_params --enable_htp' + @echo "Deeplab v3 model conversion completed" + @# Can't use deeplabv3_htp.dlc as make target since this file is present on failure + @touch $@ + +gen-sdm865-dlc-info: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + sdm865-dlc + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/dlc \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '\ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/mobilenet_edgetpu_224_1.0_hta.dlc && \ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/ssd_mobilenet_v2_qat_hta.dlc && \ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/deeplabv3_hta.dlc' + +gen-sdm888-dlc-info: \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp ${BUILDDIR}/datasets.stamp \ + sdm888-dlc + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/dlc \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c '\ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/mobilenet_edgetpu_224_1.0_htp.dlc && \ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/ssd_mobiledet_qat_htp.dlc && \ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/deeplabv3_htp.dlc && \ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info -i /dlc/mobilenet_edgetpu_224_1.0_htp_batched.dlc' + +test: ${BUILDDIR}/mlperf_snpe${OSVER}_docker_image.stamp + @docker run \ + -e PYTHONPATH=/snpe_sdk/lib/python \ + -e LD_LIBRARY_PATH=/snpe_sdk/lib/x86_64-linux-clang \ + -v ${SNPE_SDK}:/snpe_sdk \ + -v ${DLCBUILDDIR}:/dlc \ + -u ${USERID}:${GROUPID} \ + mlperf_snpe${OSVER}:latest \ + /bin/bash -c '\ + /snpe_sdk/bin/x86_64-linux-clang/snpe-dlc-info' + +clean: + @rm -rf ${BUILDDIR}/DLC + diff --git a/mobile_back_qti/DLC/argmax-quant.json b/mobile_back_qti/DLC/argmax-quant.json new file mode 100644 index 000000000..7346a088d --- /dev/null +++ b/mobile_back_qti/DLC/argmax-quant.json @@ -0,0 +1,13 @@ +{ + "activation_encodings": { + "ArgMax:0": [{ + "min": 0, + "max": 255, + "scale": 1, + "offset": 0, + "is_symmetric": "False", + "bitwidth": 8 + }] + }, + "param_encodings": {} +} diff --git a/mobile_back_qti/README.md b/mobile_back_qti/README.md new file mode 100644 index 000000000..b9b366c72 --- /dev/null +++ b/mobile_back_qti/README.md @@ -0,0 +1,96 @@ +# MLPerf Mobile App SNPE Backend + +This subdirectory contains the QTI backend for the MLPerf mobile app, an app-based +implementationn of [MLPerf Inference](https://github.com/mlperf/inference) tasks. + +## Overview + +This repository builds the libqtibackend.so backend and prepares the libraries and +SNPE DLC files for integration with the MLPerf app. These DLC files have been +uploaded to https://github.com/mlcommons/mobile_models. + +## Requirements + +* [SNPE SDK](https://developer.qualcomm.com/software/qualcomm-neural-processing-sdk) + * Version 1.48.0 +* Linux machine capable of running Ubuntu 18.04 docker images + +After downloading and unzipping the SNPE SDK, make sure to set SNPE_SDK to its location: +``` +cd /opt +unzip snpe-1.48.0.2554.zip +export SNPE_SDK=/opt/snpe-1.48.0.2554 +``` + +### Optional + +If you wish to rebuild the DLC files yourself, you will have these additional requirements: + +* Imagenet dataset (LSVRC2012_img_val.tar) put in the build/imagenet/downloads directory +* Linux machine also capable of running Tensorflow debian based docker images + +Use your browser to download the SNPE SDK using the links above. + +Create your Github personal access token. +``` +export GITHUB_TOKEN= +cd DLC/ && make +``` +It will take a couple hours on an 8-core Xeon workstation to generate the DLC files. + +## Building the MLPerf app with the QTI backend + +Manual steps: +* Extract the SNPE SDK (from Requirements above) and set SNPE_SDK to its location. + +* If you have an HTTP proxy, you may need the following +``` +sudo apt install ca-certificates-java +export USE_PROXY_WORKAROUND=1 +``` + +Clone mlperf_app_open and build with the following build commands. +``` +git clone https://github.com/mlcommons/mobile_app_open +cd mobile_app_open +make WITH_QTI=1 app +``` + +This will build the QTI backend into the MLPerf app. + +## Building the QTI backend lib + +To build only the QTI backend: +``` +git clone https://github.com/mlcommons/mobile_app_open +make WITH_QTI=1 libqtibackend +``` + +## Backend Specific Task Config file + +The task config settings are embedded in libqtibackend.so. These settings contain the +backend specific data for each task to be run. This backend assumes a few things about +the settings: + +1. The MobileBERT task sets the configuration name to "TFLite GPU". The accelerator + value is gpu_f16 to use TFLite GPU delegate. +2. All other models use "SNPE" for the configuration name and use "snpe aip", "snpe dsp", + "psnpe aip", or "psnpe dsp" for the accelerator value when using SNPE. + +## FAQ + +#### Do I need to build the DLC files? + +No, the information to build the DLC files is only to show how they are created. + +#### What devices does this backend support? + +This backend only supports SDM865/SDM865 Pro and SDM888 devices. Other Snapdragon based +devices will not run the MLPerf app. Future updates of the app will provide +additional device support. + +#### Is SNPE used to run all the models? + +No, there is a TFLite wrapper invoked by this backend to run the MobileBERT model. The +other models use SNPE. + diff --git a/mobile_back_qti/builddir.mk b/mobile_back_qti/builddir.mk new file mode 100644 index 000000000..b34335b92 --- /dev/null +++ b/mobile_back_qti/builddir.mk @@ -0,0 +1,24 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +this_mkfile:=$(abspath $(lastword $(MAKEFILE_LIST))) +TOPDIR:=$(shell dirname ${this_mkfile}) +APP_DIR=${TOPDIR}/../ +BUILDDIR=${APP_DIR}/output +SNPE_VERSION=$(shell grep SNPE_VERSION variables.bzl | cut -d\" -f2) + +USERID=$(shell id -u) +GROUPID=$(shell id -g) + diff --git a/mobile_back_qti/cpp/backend_qti/BUILD b/mobile_back_qti/cpp/backend_qti/BUILD new file mode 100644 index 000000000..27d814dd6 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/BUILD @@ -0,0 +1,149 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +# +# This file contains an application that loads and executes a neural network +# using the SNPE C++ API and saves the MLPerf output to a file. +# Inputs to and outputs from the network are conveyed in binary form as single +# precision floating point values. +# +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + +package( + default_visibility = ["//visibility:public"], + licenses = ["notice"], # Apache 2.0 +) + +load("//mobile_back_qti:variables.bzl", "SNPE_VERSION") + +config_setting( + name = "android_arm64", + values = {"cpu": "arm64-v8a"}, +) + +snpe_copts = [ + "-Imobile_back_qti/" + SNPE_VERSION + "/include/zdl", + "-fexceptions", "-lc++_shared" +] + +load( + "@org_tensorflow//tensorflow/lite:build_def.bzl", + "tflite_copts", + "tflite_jni_binary", +) + +cc_library( + name = "qti_rpcmem", + srcs = ["rpcmem.cc"], + hdrs = ["rpcmem.h"], + copts = tflite_copts() + snpe_copts, + deps = ["@org_tensorflow//tensorflow/core:tflite_portable_logging"], + alwayslink = 1, +) + +cc_library( + name = "qti_allocator", + srcs = ["allocator.cc"], + hdrs = ["allocator.h"], + copts = tflite_copts() + snpe_copts, + deps = [ + ":qti_rpcmem", + "@org_tensorflow//tensorflow/core:tflite_portable_logging", + ], + alwayslink = 1, +) + +cc_library( + name = "qti_allocator_x86", + srcs = ["allocator.cc"], + hdrs = ["allocator.h"], + deps = [ + ":qti_rpcmem", + "@org_tensorflow//tensorflow/core:tflite_portable_logging", + ], + alwayslink = 1, +) + +cc_library( + name = "qti_c", + srcs = select({ + "android_arm64": [ + "qti_c.cc", + "cpuctrl.cc", + "tflite_c.cc", + "qti_backend_helper.cc", + ], + }), + hdrs = [] + select({ + "android_arm64": [ + "qti_settings.h", + "cpuctrl.h", + "tflite_c.h", + "qti_backend_helper.h", + "mlperf_helper.h", + ], + }), + copts = tflite_copts() + snpe_copts, + deps = [ + "//android/cpp/c:headers", + ":qti_allocator", + ] + select({ + "android_arm64": [ + "@org_tensorflow//tensorflow/lite/c:c_api", + "@org_tensorflow//tensorflow/lite/c:common", + "@org_tensorflow//tensorflow/lite/delegates/gpu:delegate", + "@org_tensorflow//tensorflow/core:tflite_portable_logging", + "//mobile_back_qti:snpe", + ], + }), + alwayslink = 1, +) + +tflite_jni_binary( + name = "libqtibackend.so", + linkscript = "//android/cpp/c:version_script.lds", + deps = [ + ":qti_c", + ], +) + +cc_binary( + name = "qti_backend_test", + srcs = [] + select({ + "android_arm64": [ + "test.cc", + ], + }), + linkopts = ["-pie"], + linkstatic = 1, + deps = [] + select({ + "android_arm64": [ + ":libqtibackend.so", + "//android/cpp/c:headers", + "@org_tensorflow//tensorflow/lite:shared_library", + ], + }), +) + +cc_binary( + name = "allocator_test", + srcs = [ + "allocator_test.cc", + ], + linkstatic = 1, + deps = [ + ":qti_allocator_x86", + ], +) diff --git a/mobile_back_qti/cpp/backend_qti/allocator.cc b/mobile_back_qti/cpp/backend_qti/allocator.cc new file mode 100644 index 000000000..b6f5e2788 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/allocator.cc @@ -0,0 +1,56 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "allocator.h" + +// Map of allocation size to Chunk allocator instance +std::map &getAllocator() { + static std::map allocator; + return allocator; +} + +std::map ChunkAllocator::Block::block_map_; + +void* ChunkAllocator::GetBuffer(size_t n, size_t chunks_per_block) { + // See if allocator for this allocation size exists + if (!getAllocator().count(n)) { + getAllocator().emplace(std::make_pair(n, ChunkAllocator(n, chunks_per_block))); + } + return getAllocator().at(n).GetChunk(); +} + +void ChunkAllocator::ReleaseBuffer(void* p) { + Block* block = Block::block_map_[p]; + getAllocator().at(block->GetChunkSize()).ReleaseChunk(block, p); +} + +void* ChunkAllocator::GetBatchPtr(void* p) { + return Block::block_map_[p]->ptr_; +} + +void ChunkAllocator::DumpState() { + printf("================ DumpState ==============\n"); + for (auto it : getAllocator()) { + printf("ChunkAllocator:\n"); + it.second.DumpAllocatorState(); + } +} + +RpcMem &ChunkAllocator::getRpcMem() +{ + static RpcMem rpcmem; + return rpcmem; +} + diff --git a/mobile_back_qti/cpp/backend_qti/allocator.h b/mobile_back_qti/cpp/backend_qti/allocator.h new file mode 100644 index 000000000..cea1f4ba9 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/allocator.h @@ -0,0 +1,177 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef ALLOCATOR_H +#define ALLOCATOR_H + +#include +#include +#include + +#include "rpcmem.h" + +// This allocator assumes all allocations and frees are done in order +class ChunkAllocator { + public: + static void *GetBuffer(size_t n, size_t chunks_per_block); + + static void ReleaseBuffer(void *p); + + static void *GetBatchPtr(void *p); + + static void DumpState(); + + static RpcMem &getRpcMem(); + + private: + ChunkAllocator(); + + ChunkAllocator(size_t chunk_size, size_t chunks_per_block) + : chunk_size_(chunk_size), chunks_per_block_(chunks_per_block) {} + + class Block { + public: + Block(size_t chunk_size, int32_t num_chunks) + : num_chunks_(num_chunks), + free_chunks_(num_chunks), + chunk_size_(chunk_size) { + ptr_ = getRpcMem().Alloc(chunk_size * num_chunks); + block_map_[ptr_] = this; + } + + void *GetChunk() { + if (free_chunks_) { + free_chunks_--; + uint8_t *p = (uint8_t *)ptr_; + return (void *)&p[(num_chunks_ - free_chunks_ - 1) * chunk_size_]; + } + return nullptr; + } + + void ReleaseChunk(void *p) { + free_chunks_++; + if (free_chunks_ == num_chunks_) { + getRpcMem().Free(ptr_); + ptr_ = nullptr; + } + Block::block_map_.erase(p); + } + + bool IsFull() { return free_chunks_ == 0; } + bool IsEmpty() { return free_chunks_ == num_chunks_; } + + uint32_t GetChunkSize() { return chunk_size_; } + void DumpState() { + printf(" Block (%p):\n", this); + printf(" NumChunks %u\n", num_chunks_); + printf(" FreeChunks %u\n", free_chunks_); + } + + ~Block() { + if (ptr_ != nullptr) std::free(ptr_); + } + + // Map allocated pointers to their block + static std::map block_map_; + + void *ptr_ = nullptr; + + private: + uint32_t num_chunks_; + uint32_t free_chunks_; + uint32_t chunk_size_; + }; + + void *GetChunk() { + if (block_list_.empty() || block_list_.back()->IsFull()) { + Block *block = new Block(chunk_size_, chunks_per_block_); + block_list_.push_back(block); + } + Block *block = block_list_.back(); + void *p = block_list_.back()->GetChunk(); + Block::block_map_[p] = block; + return p; + } + + void ReleaseChunk(Block *block, void *p) { + // Block::ReleaseChunk updates Block::block_map_ + block->ReleaseChunk(p); + if (block->IsEmpty()) { + block_list_.remove(block); + delete block; + } + } + + void DumpAllocatorState() { + printf(" ChunkSize %lu\n", chunk_size_); + printf(" ChunksPerBlock %lu\n", chunks_per_block_); + printf(" Blocks:\n"); + for (auto it : block_list_) { + it->DumpState(); + } + } + + // List of all allocated blocks for this Chunk allocator instance + // FIXME this should be a unique_map + std::list block_list_; + const size_t chunk_size_; + const size_t chunks_per_block_; +}; + +template +struct Allocator { + typedef T value_type; + + Allocator() = default; + + template + constexpr Allocator(const Allocator &) noexcept {} + + [[nodiscard]] T *allocate(std::size_t n) { + if (auto p = static_cast( + ChunkAllocator::getRpcMem().Alloc(n * sizeof(T)))) { + return p; + } + return nullptr; + } + + void deallocate(T *p, std::size_t n) noexcept { + ChunkAllocator::getRpcMem().Free(p); + } +}; + +static void *get_ion_buffer(size_t n) { + void *p = ChunkAllocator::GetBuffer(n, 3); + // LOG(INFO) << "QTI backend SNPE allocator " << n << " bytes at " << p; + return p; +} + +static void *std_get_buffer(size_t n) { + void *p = std::malloc(n); + // LOG(INFO) << "QTI backend SDT allocator " << n << " bytes at " << p; + return p; +} + +static void release_ion_buffer(void *p) { + // LOG(INFO) << "QTI backend SNPE free " << p; + ChunkAllocator::ReleaseBuffer(p); +} + +static void std_release_buffer(void *p) { + // LOG(INFO) << "QTI backend STD free " << p; + std::free(p); +} + +#endif diff --git a/mobile_back_qti/cpp/backend_qti/allocator_test.cc b/mobile_back_qti/cpp/backend_qti/allocator_test.cc new file mode 100644 index 000000000..1c0c5f05d --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/allocator_test.cc @@ -0,0 +1,67 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "allocator.h" + +void doCopy(void* dest, size_t n) { + printf("Verifying %p\n", dest); + for (size_t x = 0; x < n; x++) { + ((uint8_t*)(dest))[x] = 1; + } +} + +int main() { + void* a1 = ChunkAllocator::GetBuffer(100, 3); + ChunkAllocator::DumpState(); + doCopy(a1, 100); + void* a2 = ChunkAllocator::GetBuffer(100, 3); + ChunkAllocator::DumpState(); + doCopy(a2, 100); + void* a3 = ChunkAllocator::GetBuffer(100, 3); + ChunkAllocator::DumpState(); + doCopy(a3, 100); + void* a4 = ChunkAllocator::GetBuffer(100, 3); + doCopy(a4, 100); + void* a5 = ChunkAllocator::GetBuffer(100, 3); + doCopy(a5, 100); + ChunkAllocator::DumpState(); + + void* b1 = ChunkAllocator::GetBuffer(150, 4); + doCopy(b1, 150); + void* b2 = ChunkAllocator::GetBuffer(150, 4); + doCopy(b2, 150); + ChunkAllocator::DumpState(); + void* b3 = ChunkAllocator::GetBuffer(150, 4); + doCopy(b3, 150); + void* b4 = ChunkAllocator::GetBuffer(150, 4); + doCopy(b4, 150); + void* b5 = ChunkAllocator::GetBuffer(150, 4); + doCopy(b5, 150); + ChunkAllocator::DumpState(); + + ChunkAllocator::ReleaseBuffer(a1); + ChunkAllocator::ReleaseBuffer(a2); + ChunkAllocator::DumpState(); + ChunkAllocator::ReleaseBuffer(a3); + ChunkAllocator::ReleaseBuffer(a4); + ChunkAllocator::ReleaseBuffer(a5); + ChunkAllocator::DumpState(); + ChunkAllocator::ReleaseBuffer(b1); + ChunkAllocator::ReleaseBuffer(b2); + ChunkAllocator::DumpState(); + ChunkAllocator::ReleaseBuffer(b3); + ChunkAllocator::ReleaseBuffer(b4); + ChunkAllocator::ReleaseBuffer(b5); + ChunkAllocator::DumpState(); +} diff --git a/mobile_back_qti/cpp/backend_qti/cpuctrl.cc b/mobile_back_qti/cpp/backend_qti/cpuctrl.cc new file mode 100644 index 000000000..ec56980c4 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/cpuctrl.cc @@ -0,0 +1,177 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "cpuctrl.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "tensorflow/core/platform/logging.h" + +using namespace std::chrono; + +#define SET_AFFINITY(a, b) sched_setaffinity(gettid(), a, b) +#define GET_AFFINITY(a, b) sched_getaffinity(gettid(), a, b) + +#define SLEEPMS 2 + +static uint32_t soc_id_g = 0; + +static bool active_g = false; +static std::thread *thread_ = nullptr; +static cpu_set_t cpusetLow_g; +static cpu_set_t cpusetHigh_g; +static cpu_set_t cpusetall_g; + +static void loop(void *unused) { + (void)unused; + active_g = true; + while (active_g) { + auto now = + duration_cast(system_clock::now().time_since_epoch()); + if (now.count() % 100 == 0 && active_g) { + usleep(SLEEPMS * 1000); + } else { + for (int i = 0; i < 100; i++) { + // Prevent compiler from optimizing away busy loop + __asm__ __volatile__("" : "+g"(i) : :); + } + } + } +} + +void CpuCtrl::startLoad() { + if (active_g) { + return; + } + thread_ = new std::thread(loop, nullptr); +} + +void CpuCtrl::stopLoad() { + active_g = false; + if (thread_) { + thread_->join(); + } + delete thread_; + thread_ = nullptr; +} + +void CpuCtrl::lowLatency() { SET_AFFINITY(sizeof(cpu_set_t), &cpusetLow_g); } + +void CpuCtrl::normalLatency() { SET_AFFINITY(sizeof(cpu_set_t), &cpusetall_g); } + +void CpuCtrl::highLatency() { SET_AFFINITY(sizeof(cpu_set_t), &cpusetHigh_g); } + +bool CpuCtrl::isSnapDragon(const char *manufacturer) { + bool is_qcom = false; + + if (strncmp("QUALCOMM", manufacturer, 7) == 0) { + // This is a test device + LOG(INFO) << "QTI test device detected"; + is_qcom = true; + } else { + static EGLint const attribute_list[] = {EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, EGL_NONE}; + + EGLDisplay display; + EGLConfig config; + EGLContext context; + EGLSurface surface; + EGLint num_config; + + /* get an EGL display connection */ + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + /* initialize the EGL display connection */ + eglInitialize(display, NULL, NULL); + /* get an appropriate EGL frame buffer configuration */ + eglChooseConfig(display, attribute_list, &config, 1, &num_config); + /* create an EGL rendering context */ + context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL); + /* connect the context to the surface */ + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context); + + const unsigned char *vendor = glGetString(GL_VENDOR); + + if (strcmp("Qualcomm", (const char *)vendor) == 0) { + is_qcom = true; + } + + LOG(INFO) << "vendor: " << vendor; + } + return is_qcom; +} + +uint32_t CpuCtrl::getSocId() { + if (soc_id_g == 0) { + std::ifstream in_file; + std::vector line(5); + in_file.open("/sys/devices/soc0/soc_id"); + if (in_file.fail()) { + in_file.open("/sys/devices/system/soc/soc0/id"); + } + if (in_file.fail()) { + return 0; + } + + in_file.read(line.data(), 5); + in_file.close(); + soc_id_g = (uint32_t)std::atoi(line.data()); + + std::vector allcores; + std::vector low_latency_cores; + std::vector high_latency_cores; + int maxcores = 0; + if (soc_id_g == SDM888 || soc_id_g == SDM865) { + high_latency_cores.emplace_back(0); + high_latency_cores.emplace_back(1); + high_latency_cores.emplace_back(2); + high_latency_cores.emplace_back(3); + maxcores = 8; + } + + if (soc_id_g == SDM888 || soc_id_g == SDM865) { + low_latency_cores.emplace_back(4); + low_latency_cores.emplace_back(5); + low_latency_cores.emplace_back(6); + low_latency_cores.emplace_back(7); + maxcores = 8; + } + + for (auto i = 0; i < maxcores; i++) { + allcores.emplace_back(i); + } + + CPU_ZERO(&cpusetLow_g); + for (auto core : low_latency_cores) { + CPU_SET(core, &cpusetLow_g); + } + CPU_ZERO(&cpusetHigh_g); + for (auto core : high_latency_cores) { + CPU_SET(core, &cpusetHigh_g); + } + CPU_ZERO(&cpusetall_g); + for (auto core : allcores) { + CPU_SET(core, &cpusetall_g); + } + } + LOG(INFO) << "SOC ID is " << soc_id_g; + return soc_id_g; +} diff --git a/mobile_back_qti/cpp/backend_qti/cpuctrl.h b/mobile_back_qti/cpp/backend_qti/cpuctrl.h new file mode 100644 index 000000000..a778661f6 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/cpuctrl.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#pragma once + +#include +#include +#include + +#define SDM865 356 +#define SDM888 415 + +class CpuCtrl { + public: + static void startLoad(); + static void stopLoad(); + static void lowLatency(); + static void normalLatency(); + static void highLatency(); + static uint32_t getSocId(); + static bool isSnapDragon(const char *manufacturer); + + private: + CpuCtrl() = delete; + ~CpuCtrl() = delete; +}; diff --git a/mobile_back_qti/cpp/backend_qti/mlperf_helper.h b/mobile_back_qti/cpp/backend_qti/mlperf_helper.h new file mode 100644 index 000000000..5612c0733 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/mlperf_helper.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef MLPERFHELPER_H +#define MLPERFHELPER_H + +#include "android/cpp/c/backend_c.h" +#include "android/cpp/c/type.h" +#include "qti_backend_helper.h" +#include "tensorflow/core/platform/logging.h" + +static void process_config(const mlperf_backend_configuration_t *configs, + QTIBackendHelper *backend_data) { + backend_data->is_tflite_ = false; + backend_data->batchSize_ = 1; + backend_data->useSnpe_ = false; + + std::string &delegate = backend_data->delegate_; + delegate = configs->accelerator; + if ((delegate == "gpu_f16") || (delegate == "nnapi-qti-dsp") || + (delegate == "nnapi-qti-gpu")) { + backend_data->is_tflite_ = true; + } else if (strncmp(configs->accelerator, "snpe", 4) == 0) { + backend_data->useSnpe_ = true; + } else if (strncmp(configs->accelerator, "psnpe", 5) == 0) { + backend_data->useSnpe_ = false; + } else { + LOG(FATAL) << "Error: Unsupported delegate " << delegate; + } + + // Batch size is zero if not specified + backend_data->batchSize_ = + (configs->batch_size == 0) ? 1 : configs->batch_size; + + // Handle custom settings + for (int i = 0; i < configs->count; ++i) { + if (strcmp(configs->keys[i], "scenario") == 0) { + backend_data->scenario_ = configs->values[i]; + } else if (strcmp(configs->keys[i], "snpeOutputLayers") == 0) { + backend_data->snpe_output_layers_ = configs->values[i]; + } else if (strcmp(configs->keys[i], "bgLoad") == 0) { + backend_data->bgLoad_ = true; + } + } + + LOG(INFO) << "Config: delegate: " << delegate + << " scenario: " << backend_data->scenario_ + << " output: " << backend_data->snpe_output_layers_ + << " isTfLite: " << backend_data->is_tflite_ + << " batchSize: " << backend_data->batchSize_ + << " useSNPE: " << backend_data->useSnpe_ + << " bgLoad: " << backend_data->bgLoad_; +} + +#endif diff --git a/mobile_back_qti/cpp/backend_qti/qti_backend_helper.cc b/mobile_back_qti/cpp/backend_qti/qti_backend_helper.cc new file mode 100644 index 000000000..6fe18cbf5 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/qti_backend_helper.cc @@ -0,0 +1,493 @@ +/* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include "DiagLog/IDiagLog.hpp" +#include "DlContainer/IDlContainer.hpp" +#include "DlSystem/DlEnums.hpp" +#include "DlSystem/DlError.hpp" +#include "DlSystem/IBufferAttributes.hpp" +#include "DlSystem/IUserBuffer.hpp" +#include "DlSystem/PlatformConfig.hpp" +#include "DlSystem/StringList.hpp" +#include "DlSystem/TensorMap.hpp" +#include "DlSystem/TensorShape.hpp" +#include "DlSystem/TensorShapeMap.hpp" +#include "DlSystem/UserBufferMap.hpp" +#include "SNPE/SNPEBuilder.hpp" +#include "SNPE/SNPEFactory.hpp" +#include "SNPE/UserBufferList.hpp" +#include "absl/strings/ascii.h" +#include "cpuctrl.h" + +#include "tensorflow/core/platform/logging.h" +#include "tflite_c.h" + +#include "qti_backend_helper.h" + +int isSignedStatus = DEFAULT; + +static long calcSizeFromDims(const size_t rank, + const zdl::DlSystem::Dimension *dims) { + if (rank == 0) return 0; + size_t size = 1; + for (size_t i = rank; i > 0; i--) { + if (*dims != 0) + size *= *dims; + else + size *= 10; + dims++; + } + return (long)size; +} + +// Helper for splitting tokenized strings +static void split(std::vector &split_string, + const std::string &tokenized_string, const char separator) { + split_string.clear(); + std::istringstream tokenized_string_stream(tokenized_string); + + while (!tokenized_string_stream.eof()) { + std::string value; + getline(tokenized_string_stream, value, separator); + if (!value.empty()) { + split_string.push_back(value); + } + } +} + +static zdl::DlSystem::StringList ResolveOutputLayerNames(std::string &line) { + zdl::DlSystem::StringList outputLayers; + if (!line.empty()) { + std::vector names; + split(names, line.substr(0), ','); + for (auto &name : names) outputLayers.append(name.c_str()); + } + return outputLayers; +} + +static std::vector calcStrides(zdl::DlSystem::TensorShape dims, + size_t elementSize) { + std::vector strides(dims.rank()); + strides[strides.size() - 1] = elementSize; + size_t stride = strides[strides.size() - 1]; + for (size_t i = dims.rank() - 1; i > 0; i--) { + if (dims[i] != 0) + stride *= dims[i]; + else + stride *= 10; + strides[i - 1] = stride; + } + return strides; +} + +static zdl::DlSystem::Runtime_t Str2Delegate(const std::string &delegate) { + if (absl::AsciiStrToLower(delegate) == "snpe dsp") { + if (!zdl::SNPE::SNPEFactory::isRuntimeAvailable( + zdl::DlSystem::Runtime_t::DSP, + zdl::DlSystem::RuntimeCheckOption_t::BASIC_CHECK)) { + // This platform supports DSP runtime + LOG(FATAL) << "DSP runtime is not available on this platform"; + } else { + if (isSignedStatus == DEFAULT) { + if (zdl::SNPE::SNPEFactory::isRuntimeAvailable( + zdl::DlSystem::Runtime_t::DSP, + zdl::DlSystem::RuntimeCheckOption_t::NORMAL_CHECK)) { + isSignedStatus = SIGNED_PD; + LOG(INFO) + << "DSP runtime is available on this platform with SignedPD"; + } else { + isSignedStatus = UNSIGNED_PD; + LOG(INFO) + << "DSP runtime is available on this platform with UnSignedPD"; + } + } + return zdl::DlSystem::Runtime_t::DSP; + } + } else if (absl::AsciiStrToLower(delegate) == "snpe aip") { + if (!zdl::SNPE::SNPEFactory::isRuntimeAvailable( + zdl::DlSystem::Runtime_t::AIP_FIXED_TF, + zdl::DlSystem::RuntimeCheckOption_t::BASIC_CHECK)) { + // This platform supports AIP runtime + LOG(FATAL) << "AIP runtime is not available on this platform"; + } else { + if (isSignedStatus == DEFAULT) { + if (zdl::SNPE::SNPEFactory::isRuntimeAvailable( + zdl::DlSystem::Runtime_t::AIP_FIXED_TF, + zdl::DlSystem::RuntimeCheckOption_t::NORMAL_CHECK)) { + isSignedStatus = SIGNED_PD; + LOG(INFO) + << "AIP runtime is available on this platform with SignedPD"; + } else { + isSignedStatus = UNSIGNED_PD; + LOG(INFO) + << "AIP runtime is available on this platform with UnSignedPD"; + } + } + return zdl::DlSystem::Runtime_t::AIP_FIXED_TF; + } + } else if (absl::AsciiStrToLower(delegate) == "snpe gpu") { + if (!zdl::SNPE::SNPEFactory::isRuntimeAvailable( + zdl::DlSystem::Runtime_t::GPU)) { + LOG(FATAL) << "GPU runtime is not available on this platform"; + } else { + LOG(INFO) << "GPU runtime is available on this platform"; + return zdl::DlSystem::Runtime_t::GPU; + } + } + return zdl::DlSystem::Runtime_t::CPU; +} + +void QTIBackendHelper::use_psnpe(const char *model_path) { + uint32_t soc_id = CpuCtrl::getSocId(); + uint32_t numInits = get_num_inits(); + LOG(INFO) << "numInits: " << numInits; + + bool psnpe_buildStatus = false; + // Init cache generated on device giving better performance. + // So build the DLC twice to use the init cache generated in the first run + for (int i = 0; i < numInits; i++) { + // Open the DL container that contains the network to execute. + std::unique_ptr container; + // destroys previous snpe instance and creates a new one. + psnpe_.reset(new zdl::PSNPE::PSNPE()); + // Loads the container after destroying the previous instance + container = zdl::DlContainer::IDlContainer::open(model_path); + if (!container) { + LOG(FATAL) << "Container is not available " << model_path; + } + + zdl::PSNPE::BuildConfig buildConfig; + buildConfig.container = container.get(); + buildConfig.runtimeConfigList = runtimeConfigsList; + buildConfig.inputOutputTransmissionMode = + zdl::PSNPE::InputOutputTransmissionMode::sync; + + zdl::DlSystem::StringList outputLayers = + ResolveOutputLayerNames(snpe_output_layers_); + + zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); + snpeBuilder.setOutputLayers(outputLayers); + + if (outputLayers.size() > 0) { + buildConfig.outputBufferNames = outputLayers; + } + + std::string platformOptionStr = ""; + if (useDspFeatures && isSignedStatus == UNSIGNED_PD) { + // use unsignedPD feature for untrusted app. + platformOptionStr += "unsignedPD:ON"; + } + + // These features are not for SDM865, so turning them off. + if (useDspFeatures && soc_id == SDM888) { + // use Zero copy for input and output buffers. + // Requires rpc registered ion buffers. + platformOptionStr += ";useDspZeroCopy:ON"; + platformOptionStr += ";dspPowerSettingContext:ON"; + buildConfig.enableInitCache = true; + } + buildConfig.platformOptions = platformOptionStr; + + zdl::DlSystem::PlatformConfig platformConfig; + bool setSuccess = platformConfig.setPlatformOptions(platformOptionStr); + bool isValid = platformConfig.isOptionsValid(); + if (!isValid) { + LOG(INFO) << "platformconfig option is invalid"; + } + snpeBuilder.setPlatformConfig(platformConfig); + snpe_ = snpeBuilder.build(); + + psnpe_buildStatus = psnpe_->build(buildConfig); + + // Saves the container if there is a modification in any of the record. + if (numInits > 1) container->save(model_path); + } + + if (!psnpe_buildStatus) { + LOG(FATAL) << "Error in init of the model "; + } +} + +void QTIBackendHelper::use_snpe(const char *model_path) { + uint32_t soc_id = CpuCtrl::getSocId(); + uint32_t numInits = get_num_inits(); + LOG(INFO) << "numInits: " << numInits; + + // Use SNPE + for (int i = 0; i < numInits; i++) { + // Open the DL container that contains the network to execute. + std::unique_ptr container; + // Loads the container after destroying the previous instance + container = zdl::DlContainer::IDlContainer::open(model_path); + if (!container) { + LOG(FATAL) << "Container is not available " << model_path; + } + + zdl::SNPE::SNPEBuilder snpeBuilder(container.get()); + zdl::DlSystem::StringList outputLayers = + ResolveOutputLayerNames(snpe_output_layers_); + + snpeBuilder + .setPerformanceProfile(zdl::DlSystem::PerformanceProfile_t::BURST) + .setExecutionPriorityHint(zdl::DlSystem::ExecutionPriorityHint_t::HIGH) + .setRuntimeProcessorOrder(inputRuntimeList) + .setUseUserSuppliedBuffers(true) + .setOutputLayers(outputLayers); + + std::string platformOptionStr = ""; + if (useDspFeatures && isSignedStatus == UNSIGNED_PD) { + // use unsignedPD feature for untrusted app. + platformOptionStr += "unsignedPD:ON"; + } + + // These features are not for SDM865, so turning them off. + if (useDspFeatures && soc_id == SDM888) { + // use Zero copy for input and output buffers. + // Requires rpc registered ion buffers. + platformOptionStr += ";useDspZeroCopy:ON"; + platformOptionStr += ";dspPowerSettingContext:ON"; + snpeBuilder.setInitCacheMode(true); + } + zdl::DlSystem::PlatformConfig platformConfig; + bool setSuccess = platformConfig.setPlatformOptions(platformOptionStr); + bool isValid = platformConfig.isOptionsValid(); + if (!isValid) { + LOG(INFO) << "platformconfig option is invalid"; + } + snpeBuilder.setPlatformConfig(platformConfig); + snpe_ = snpeBuilder.build(); + + // Saves the container if there is a modification in any of the record. + if (numInits > 1) container->save(model_path); + } + if (!snpe_) { + LOG(FATAL) << "Error in init of the model " << snpe_; + } +} + +inline int QTIBackendHelper::get_num_inits() { + uint32_t soc_id = CpuCtrl::getSocId(); + if (!useDspFeatures || soc_id == SDM865) { + return 1; + } else { + return 2; + } +} + +void QTIBackendHelper::get_accelerator_instances(int &numDSP, int &numAIP, + int &numGPU, int &numCPU) { + uint32_t soc_id = CpuCtrl::getSocId(); + std::string &delegate = delegate_; + if (scenario_ == "Offline") { + // For 865 use DSP+AIP + if (soc_id == SDM865) { + if (delegate != "snpe aip" && delegate != "psnpe aip") { + LOG(FATAL) << "Error: Unsupported delegate for offline mode"; + } + useDspFeatures = true; + numDSP = 2; + numAIP = 6; + } else if (soc_id == SDM888) { + if (delegate != "snpe dsp" && delegate != "psnpe dsp") { + LOG(FATAL) << "Error: Unsupported delegate for offline mode"; + } + useDspFeatures = true; + numDSP = 2; + numAIP = 0; + } + } else { + if (delegate == "snpe dsp" || delegate == "psnpe dsp") { + numDSP = 1; + useDspFeatures = true; + } else if (delegate == "snpe aip" || delegate == "psnpe aip") { + numAIP = 1; + useDspFeatures = true; + } else if (delegate == "snpe gpu" || delegate == "psnpe gpu") { + numGPU = 1; + useDspFeatures = false; + } else if (delegate == "snpe cpu" || delegate == "psnpe cpu") { + numCPU = 1; + useDspFeatures = false; + } else { + LOG(FATAL) << "Error: Unsupported delegate " << delegate << " SoC ID " + << soc_id; + } + } + LOG(INFO) << "Using " << numDSP << " dsp " << numAIP << " aip " << numGPU + << " gpu and " << numCPU << " cpu"; +} + +void QTIBackendHelper::map_inputs() { + zdl::DlSystem::UserBufferMap inputMap; + for (int bi = 0; bi < batchSize_ / input_batch_; bi++) { + for (const auto &name : networkInputTensorNames_) { + zdl::DlSystem::IUserBufferFactory &ubFactory = + zdl::SNPE::SNPEFactory::getUserBufferFactory(); + auto ubaOpt = snpe_->getInputOutputBufferAttributes(name); + long bufSize = calcSizeFromDims((*ubaOpt)->getDims().rank(), + (*ubaOpt)->getDims().getDimensions()); + std::vector strides; + std::unique_ptr ubPtr; + + if ((*ubaOpt)->getEncodingType() == + zdl::DlSystem::UserBufferEncoding::ElementType_t::FLOAT) { + // Prepare float buffer + bufSize *= sizeof(float); + std::vector inputBuffer(bufSize); + strides = calcStrides((*ubaOpt)->getDims(), sizeof(float)); + zdl::DlSystem::UserBufferEncodingFloat ubeFloat; + + ubPtr = + ubFactory.createUserBuffer(std::move(inputBuffer.data()), + inputBuffer.size(), strides, &ubeFloat); + inputMap.add(name, ubPtr.release()); + } else { + // Prepare tf8 buffer + bufSize *= sizeof(uint8_t); + // Pass the quantization parameters from the model to UB + zdl::DlSystem::UserBufferEncodingTfN *ubeTfN = nullptr; + zdl::DlSystem::UserBufferEncodingTfN temp(128.0, 1.0 / 255); + std::vector inputBuffer(bufSize); + strides = calcStrides((*ubaOpt)->getDims(), sizeof(uint8_t)); + ubeTfN = dynamic_cast( + (*ubaOpt)->getEncoding()); + + // Set the default QP for model which doesn't have QP. + // HTP may not need to use the QP for the current set of DLCs + // This may be required for AIP though. + LOG(INFO) << "QP parameters from model: " << ubeTfN; + if (!ubeTfN) ubeTfN = &temp; + + ubPtr = ubFactory.createUserBuffer(std::move(inputBuffer.data()), + inputBuffer.size(), strides, ubeTfN); + inputMap.add(name, ubPtr.release()); + } + } + inputMap_.push_back(inputMap); + } + bufs_.resize(batchSize_ / input_batch_); +} + +void QTIBackendHelper::map_outputs() { + zdl::DlSystem::UserBufferMap outputMap; + zdl::DlSystem::IUserBufferFactory &ubFactory = + zdl::SNPE::SNPEFactory::getUserBufferFactory(); + for (int bi = 0; bi < batchSize_ / input_batch_; bi++) { + for (const auto &name : networkOutputTensorNames_) { + auto ubaOpt = snpe_->getInputOutputBufferAttributes(name); + long bufSize = calcSizeFromDims((*ubaOpt)->getDims().rank(), + (*ubaOpt)->getDims().getDimensions()); + + output_batch_bufsize_ = bufSize; + zdl::DlSystem::UserBufferEncodingFloat userBufferEncodingFloat; + bufs_[bi].emplace( + std::string(name), + std::vector>(bufSize * sizeof(float))); + auto x = ubFactory.createUserBuffer( + bufs_[bi].at(name).data(), bufSize * sizeof(float), + calcStrides((*ubaOpt)->getDims(), sizeof(float)), + &userBufferEncodingFloat); + outputMap.add(name, x.release()); + } + outputMap_.push_back(outputMap); + } +} + +void QTIBackendHelper::get_data_formats() { + const auto &strList_input = snpe_->getInputTensorNames(); + if (!strList_input) { + throw std::runtime_error("Error obtaining Input tensor names"); + } + networkInputTensorNames_ = *strList_input; + + zdl::DlSystem::TensorShape tensorShape; + tensorShape = snpe_->getInputDimensions(); + input_batch_ = tensorShape.getDimensions()[0]; + + for (const auto &name : networkInputTensorNames_) { + auto ubaOpt = snpe_->getInputOutputBufferAttributes(name); + long bufSize = calcSizeFromDims((*ubaOpt)->getDims().rank(), + (*ubaOpt)->getDims().getDimensions()); + input_format_.push_back( + {mlperf_data_t::Type::Uint8, bufSize / input_batch_}); + } + + const auto &strList_output = snpe_->getOutputTensorNames(); + if (!strList_output) { + throw std::runtime_error("Error obtaining Output tensor names"); + } + networkOutputTensorNames_ = *strList_output; + + for (const auto &name : networkOutputTensorNames_) { + auto ubaOpt = snpe_->getInputOutputBufferAttributes(name); + long bufSize = calcSizeFromDims((*ubaOpt)->getDims().rank(), + (*ubaOpt)->getDims().getDimensions()); + output_format_.push_back( + {mlperf_data_t::Type::Float32, bufSize / input_batch_}); + } +} + +void QTIBackendHelper::set_runtime_config() { + int numDSP = 0, numAIP = 0, numGPU = 0, numCPU = 0; + get_accelerator_instances(numDSP, numAIP, numGPU, numCPU); + + zdl::DlSystem::Runtime_t runtime; + for (int i = 0; i < numDSP; i++) { + if (i == 0) { + runtime = Str2Delegate("snpe dsp"); + } + zdl::PSNPE::RuntimeConfig runtimeConfig; + runtimeConfig.runtime = runtime; + runtimeConfig.perfProfile = zdl::DlSystem::PerformanceProfile_t::BURST; + runtimeConfigsList.push_back(runtimeConfig); + inputRuntimeList.add(runtime); + } + + for (int i = 0; i < numAIP; i++) { + if (i == 0) { + runtime = Str2Delegate("snpe aip"); + } + zdl::PSNPE::RuntimeConfig runtimeConfig; + runtimeConfig.runtime = runtime; + runtimeConfig.perfProfile = zdl::DlSystem::PerformanceProfile_t::BURST; + runtimeConfigsList.push_back(runtimeConfig); + inputRuntimeList.add(runtime); + } + + for (int i = 0; i < numGPU; i++) { + if (i == 0) { + runtime = Str2Delegate("snpe gpu"); + } + zdl::PSNPE::RuntimeConfig runtimeConfig; + runtimeConfig.runtime = runtime; + runtimeConfig.perfProfile = zdl::DlSystem::PerformanceProfile_t::BURST; + runtimeConfigsList.push_back(runtimeConfig); + inputRuntimeList.add(runtime); + } + + for (int i = 0; i < numCPU; i++) { + if (i == 0) { + runtime = Str2Delegate("snpe cpu"); + } + zdl::PSNPE::RuntimeConfig runtimeConfig; + runtimeConfig.runtime = runtime; + runtimeConfig.perfProfile = zdl::DlSystem::PerformanceProfile_t::BURST; + runtimeConfigsList.push_back(runtimeConfig); + inputRuntimeList.add(runtime); + } +} diff --git a/mobile_back_qti/cpp/backend_qti/qti_backend_helper.h b/mobile_back_qti/cpp/backend_qti/qti_backend_helper.h new file mode 100644 index 000000000..d6417d275 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/qti_backend_helper.h @@ -0,0 +1,80 @@ +/* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef QTIBACKENDHELPER_H +#define QTIBACKENDHELPER_H + +#include + +#include "DlSystem/IUserBufferFactory.hpp" +#include "SNPE/PSNPE.hpp" +#include "SNPE/SNPE.hpp" +#include "android/cpp/c/backend_c.h" +#include "android/cpp/c/type.h" + +#include "allocator.h" + +#define SIGNED_PD 0 +#define UNSIGNED_PD 1 +#define DEFAULT -1 + +class QTIBackendHelper { + private: + zdl::DlSystem::RuntimeList inputRuntimeList; + zdl::PSNPE::RuntimeConfigList runtimeConfigsList; + + inline int get_num_inits(); + void get_accelerator_instances(int &numDSP, int &numAIP, int &numGPU, + int &numCPU); + + public: + using GetBufferFn = std::add_pointer::type; + using ReleaseBufferFn = std::add_pointer::type; + + const char *name_ = "snpe"; + std::string snpe_output_layers_; + std::vector input_format_; + std::vector output_format_; + std::unique_ptr psnpe_; + std::unique_ptr snpe_; + zdl::PSNPE::UserBufferList inputMap_, outputMap_; + std::vector< + std::unordered_map>>> + bufs_; + std::string scenario_; + zdl::DlSystem::StringList networkInputTensorNames_; + zdl::DlSystem::StringList networkOutputTensorNames_; + bool is_tflite_; + bool useSnpe_; + mlperf_backend_ptr_t tflite_backend; + int batchSize_; + int input_batch_; + int output_batch_bufsize_; + GetBufferFn get_buffer_; + ReleaseBufferFn release_buffer_; + bool bgLoad_; + std::string delegate_; + bool useDspFeatures = false; + + /* exposed functions */ + void use_psnpe(const char *model_path); + void use_snpe(const char *model_path); + void map_inputs(); + void map_outputs(); + void get_data_formats(); + void set_runtime_config(); +}; + +#endif diff --git a/mobile_back_qti/cpp/backend_qti/qti_c.cc b/mobile_back_qti/cpp/backend_qti/qti_c.cc new file mode 100644 index 000000000..c665e4dea --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/qti_c.cc @@ -0,0 +1,298 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include "allocator.h" +#include "cpuctrl.h" +#include "mlperf_helper.h" +#include "qti_settings.h" +#include "qti_backend_helper.h" +#include "tensorflow/core/platform/logging.h" +#include "tflite_c.h" + +static QTIBackendHelper *backend_data_g = nullptr; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Should return true if current hardware is supported. +bool mlperf_backend_matches_hardware(const char **not_allowed_message, + const char **settings, + const mlperf_device_info_t *device_info) { + if (device_info && device_info->model && device_info->manufacturer) { + LOG(INFO) << "QTI HW supported check: model: " << device_info->model + << ", manufacturer: " << device_info->manufacturer; + } + + std::ifstream in_file; + + *not_allowed_message = nullptr; + bool isQSoC = CpuCtrl::isSnapDragon(device_info->manufacturer); + LOG(INFO) << "Is QTI SOC: " << isQSoC; + + uint32_t soc_id = CpuCtrl::getSocId(); + if (isQSoC && soc_id == 0) { + // it's a QTI SOC, but can't access soc_id + *not_allowed_message = "Unsupported app"; + *settings = empty_settings.c_str(); + return true; + } + + // Check if this SoC is supported + + if (isQSoC && (soc_id == SDM865 || soc_id == SDM888)) { + // it's a QTI SOC, and the chipset is supported + *not_allowed_message = nullptr; + if (soc_id == SDM865) { + *settings = qti_settings_sdm865.c_str(); + } else { + *settings = qti_settings_sdm888.c_str(); + } + return true; + } else if (isQSoC) { + // it's a QTI SOC, but the chipset is not yet supported + *not_allowed_message = "Unsupported QTI SoC"; + *settings = empty_settings.c_str(); + return true; + } + + // It's not a QTI SOC, so set pbData to NULL + *settings = nullptr; + return false; +} + +// Create a new backend and return the pointer to it. +mlperf_backend_ptr_t mlperf_backend_create( + const char *model_path, mlperf_backend_configuration_t *configs, + const char *native_lib_path) { + if (backend_data_g) { + LOG(FATAL) << "Only one backend instance can be active at a time"; + } + LOG(INFO) << "CONFIGS count = " << configs->count; + for (int i = 0; i < configs->count; ++i) { + LOG(INFO) << "configs->[" << configs->keys[i] + << "] = " << configs->values[i]; + } + backend_data_g = new QTIBackendHelper(); + QTIBackendHelper *backend_data = backend_data_g; + + process_config(configs, backend_data); + + if (backend_data->bgLoad_) { + CpuCtrl::startLoad(); + } + + if (backend_data->is_tflite_) { + // use highlatency cores for mobileBERT + CpuCtrl::highLatency(); + backend_data->tflite_backend = tflite_backend_create(model_path, configs); + backend_data->get_buffer_ = std_get_buffer; + backend_data->release_buffer_ = std_release_buffer; + return backend_data; + } + + // use lowLatency cores for all snpe models + CpuCtrl::lowLatency(); + + // Use ION buffers for vision tasks + backend_data->get_buffer_ = get_ion_buffer; + backend_data->release_buffer_ = release_ion_buffer; + + std::stringstream adsp_lib_path; + adsp_lib_path << native_lib_path << ";"; + adsp_lib_path << "/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp"; + LOG(INFO) << "lib_path: " << adsp_lib_path.str(); + setenv("ADSP_LIBRARY_PATH", adsp_lib_path.str().c_str(), 1 /*override*/); + + // set runtime config + backend_data->set_runtime_config(); + // Use PSNPE or SNPE + if (backend_data->useSnpe_) { + backend_data->use_snpe(model_path); + } else { + backend_data->use_psnpe(model_path); + } + + backend_data->get_data_formats(); + backend_data->map_inputs(); + backend_data->map_outputs(); + + LOG(INFO) << "SNPE build completed successfully"; + + return backend_data; +} + +// Return the name of this backend. +const char *mlperf_backend_name(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + return backend_data->name_; +} + +// Destroy the backend pointer and its data. +void mlperf_backend_delete(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + LOG(INFO) << "Deleting Backend"; + if (backend_data->bgLoad_) { + CpuCtrl::stopLoad(); + } + CpuCtrl::normalLatency(); + if (backend_data->is_tflite_) { + tflite_backend_delete(backend_data->tflite_backend); + } + delete backend_data; + backend_data_g = nullptr; +} + +// Run the inference for a sample. +mlperf_status_t mlperf_backend_issue_query(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_issue_query(backend_data->tflite_backend); + } + if (!backend_data->useSnpe_) { + if (!backend_data->psnpe_->execute(backend_data->inputMap_, + backend_data->outputMap_)) { + return MLPERF_FAILURE; + } + } else { + if (!backend_data->snpe_->execute(backend_data->inputMap_[0], + backend_data->outputMap_[0])) { + return MLPERF_FAILURE; + } + } + return MLPERF_SUCCESS; +} + +// Flush the staged queries immediately. +mlperf_status_t mlperf_backend_flush_queries(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_flush_queries(backend_data->tflite_backend); + } + return MLPERF_SUCCESS; +} + +// Return the number of inputs of the model. +int32_t mlperf_backend_get_input_count(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_get_input_count(backend_data->tflite_backend); + } + return backend_data->input_format_.size(); +} + +// Return the type of the ith input. +mlperf_data_t mlperf_backend_get_input_type(mlperf_backend_ptr_t backend_ptr, + int32_t i) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_get_input_type(backend_data->tflite_backend, i); + } + return backend_data->input_format_[i]; +} + +// Set the data for ith input. +mlperf_status_t mlperf_backend_set_input(mlperf_backend_ptr_t backend_ptr, + int32_t batchIndex, int32_t i, + void *data) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_set_input(backend_data->tflite_backend, batchIndex, i, + data); + } + // The inputs are in contiguous batches of backend_data->input_batch_ inputs + if (batchIndex % backend_data->input_batch_ == 0) + for (auto &name : backend_data->networkInputTensorNames_) { + // If the value is a pad value for batched case then use the pointer to + // its contiguous block + void *batchedDataPtr = (backend_data->input_batch_ > 1) + ? ChunkAllocator::GetBatchPtr(data) + : data; + if (batchedDataPtr != data) { + LOG(INFO) << "TESTING: Using " << batchedDataPtr << " instead of " + << data; + } + backend_data->inputMap_[batchIndex / backend_data->input_batch_] + .getUserBuffer(name) + ->setBufferAddress(batchedDataPtr); + } + return MLPERF_SUCCESS; +} + +// Return the number of outputs for the model. +int32_t mlperf_backend_get_output_count(mlperf_backend_ptr_t backend_ptr) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_get_output_count(backend_data->tflite_backend); + } + return backend_data->output_format_.size(); +} +// Return the type of ith output. +mlperf_data_t mlperf_backend_get_output_type(mlperf_backend_ptr_t backend_ptr, + int32_t i) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_get_output_type(backend_data->tflite_backend, i); + } + return backend_data->output_format_[i]; +} + +// Get the data from ith output. +mlperf_status_t mlperf_backend_get_output(mlperf_backend_ptr_t backend_ptr, + uint32_t batchIndex, int32_t i, + void **data) { + QTIBackendHelper *backend_data = (QTIBackendHelper *)backend_ptr; + if (backend_data->is_tflite_) { + return tflite_backend_get_output(backend_data->tflite_backend, batchIndex, + i, data); + } + if (backend_data->snpe_output_layers_ == + "Postprocessor/BatchMultiClassNonMaxSuppression") { + /* Reorder snpe_output_layers for coco process_output */ + std::unordered_map mdet; + mdet[0] = 0; + mdet[1] = 1; + mdet[2] = 3; + mdet[3] = 2; + *data = backend_data->bufs_[batchIndex] + .at(backend_data->networkOutputTensorNames_.at(mdet.at(i))) + .data(); + return MLPERF_SUCCESS; + } + + *data = backend_data->bufs_[int(batchIndex / backend_data->input_batch_)] + .at(backend_data->networkOutputTensorNames_.at(i)) + .data() + + (batchIndex % backend_data->input_batch_) * + int(backend_data->output_batch_bufsize_ / + backend_data->input_batch_) * + sizeof(float); + return MLPERF_SUCCESS; +} + +void *mlperf_backend_get_buffer(size_t n) { + return backend_data_g->get_buffer_(n); +} + +void mlperf_backend_release_buffer(void *p) { + backend_data_g->release_buffer_(p); +} + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/mobile_back_qti/cpp/backend_qti/qti_settings.h b/mobile_back_qti/cpp/backend_qti/qti_settings.h new file mode 100644 index 000000000..21086e4af --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/qti_settings.h @@ -0,0 +1,259 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef QTI_SETTINGS_H +#define QTI_SETTINGS_H + +#include + +const std::string empty_settings = ""; + +const std::string qti_settings_sdm865 = R"SETTINGS( +common_setting { + id: "num_threads" + name: "Number of threads" + value { + value: "4" + name: "4 threads" + } +} + +common_setting { + id: "configuration" + name: "Configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "QTI" + } +} + +common_setting { + id: "share_results" + name: "Share results" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + +common_setting { + id: "cooldown" + name: "Cooldown" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + +benchmark_setting { + benchmark_id: "IC_tpu_uint8" + accelerator: "snpe aip" + accelerator_desc: "AIP" + configuration: "SNPE" + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/mobilenet_edgetpu_224_1.0_hta.dlc" +} + +benchmark_setting { + benchmark_id: "IC_tpu_uint8_offline" + accelerator: "psnpe aip" + accelerator_desc: "AIP" + configuration: "SNPE" + batch_size: 3072 + custom_setting { + id: "scenario" + value: "Offline" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/mobilenet_edgetpu_224_1.0_hta.dlc" +} + +benchmark_setting { + benchmark_id: "OD_uint8" + accelerator: "snpe aip" + accelerator_desc: "AIP" + configuration: "SNPE" + custom_setting { + id: "snpeOutputLayers" + value: "Postprocessor/BatchMultiClassNonMaxSuppression" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/ssd_mobiledet_qat_hta.dlc" +} + +benchmark_setting { + benchmark_id: "LU_gpu_float32" + accelerator: "gpu_f16" + accelerator_desc: "GPU (FP16)" + configuration: "TFLite GPU" + src: "https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/mobilebert_float_384_gpu.tflite" +} + +benchmark_setting { + benchmark_id: "IS_uint8" + accelerator: "snpe aip" + accelerator_desc: "AIP" + configuration: "SNPE" + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/deeplabv3_hta.dlc" +})SETTINGS"; + +const std::string qti_settings_sdm888 = R"SETTINGS( +common_setting { + id: "num_threads" + name: "Number of threads" + value { + value: "4" + name: "4 threads" + } + acceptable_value { + value: "1" + name: "Single thread" + } + acceptable_value { + value: "2" + name: "2 threads" + } + acceptable_value { + value: "4" + name: "4 threads" + } + acceptable_value { + value: "8" + name: "8 threads" + } + acceptable_value { + value: "16" + name: "16 threads" + } +} + +common_setting { + id: "configuration" + name: "configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "QTI" + } +} + +common_setting { + id: "share_results" + name: "Share results" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + + +common_setting { + id: "cooldown" + name: "Cooldown" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + +benchmark_setting { + benchmark_id: "IC_tpu_uint8" + accelerator: "psnpe dsp" + accelerator_desc: "HTP" + configuration: "SNPE" + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/mobilenet_edgetpu_224_1.0_htp.dlc" +} + +benchmark_setting { + benchmark_id: "IC_tpu_uint8_offline" + accelerator: "psnpe dsp" + accelerator_desc: "HTP" + configuration: "SNPE" + batch_size: 3072 + custom_setting { + id: "scenario" + value: "Offline" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/mobilenet_edgetpu_224_1.0_htp_batched.dlc" +} + +benchmark_setting { + benchmark_id: "OD_uint8" + accelerator: "psnpe dsp" + accelerator_desc: "HTP" + configuration: "SNPE" + custom_setting { + id: "snpeOutputLayers" + value: "Postprocessor/BatchMultiClassNonMaxSuppression" + } + custom_setting { + id: "bgLoad" + value: "true" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/ssd_mobiledet_qat_htp.dlc" +} + +benchmark_setting { + benchmark_id: "LU_gpu_float32" + accelerator: "gpu_f16" + accelerator_desc: "GPU (FP16)" + configuration: "TFLite" + custom_setting { + id: "bgLoad" + value: "true" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/mobilebert_float_384_gpu.tflite" +} + +benchmark_setting { + benchmark_id: "IS_uint8" + accelerator: "psnpe dsp" + accelerator_desc: "HTP" + configuration: "SNPE" + custom_setting { + id: "bgLoad" + value: "true" + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v1_0/SNPE/deeplabv3_htp.dlc" +})SETTINGS"; + +#endif diff --git a/mobile_back_qti/cpp/backend_qti/qti_tflite_test_settings.h b/mobile_back_qti/cpp/backend_qti/qti_tflite_test_settings.h new file mode 100644 index 000000000..a19a4a327 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/qti_tflite_test_settings.h @@ -0,0 +1,203 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef SNPE_SETTINGS_H +#define SNPE_SETTINGS_H + +#include + +const std::string empty_settings = ""; + +const std::string qti_settings_356 = R"SETTINGS( +common_setting { + id: "num_threads" + name: "Number of threads" + value { + value: "4" + name: "4 threads" + } +} + +common_setting { + id: "configuration" + name: "Configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "QTI" + } +} + +common_setting { + id: "share_results" + name: "Share results" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + +common_setting { + id: "cooldown" + name: "Cooldown" + value { + value: "0" + name: "false" + } + acceptable_value { + value: "1" + name: "true" + } + acceptable_value { + value: "0" + name: "false" + } +} + +benchmark_setting { + benchmark_id: "LU_gpu_float32" + setting { + id: "accelerator" + name: "accelerator" + value { + value: "gpu_f16" + name: "GPU(Float 16)" + } + } + setting { + id: "configuration" + name: "Configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "TFLite" + } + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/mobilebert_float_384_gpu.tflite" +})SETTINGS"; + +const std::string qti_settings_415 = R"SETTINGS( +common_setting { + id: "num_threads" + name: "Number of threads" + value { + value: "4" + name: "4 threads" + } + acceptable_value { + value: "1" + name: "Single thread" + } + acceptable_value { + value: "2" + name: "2 threads" + } + acceptable_value { + value: "4" + name: "4 threads" + } + acceptable_value { + value: "8" + name: "8 threads" + } + acceptable_value { + value: "16" + name: "16 threads" + } +} + +common_setting { + id: "configuration" + name: "configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "QTI" + } +} + +common_setting { + id: "share_results" + name: "Share results" + value { + value: "0" + name: "false" + } +} + +common_setting { + id: "cooldown" + name: "Cooldown" + value { + value: "0" + name: "false" + } +} + +benchmark_setting { + benchmark_id: "OD_uint8" + setting { + id: "accelerator" + name: "accelerator" + value { + value: "NNAPI" + name: "NNAPI" + } + } + setting { + id: "configuration" + name: "Configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "TFLite" + } + } + setting { + id: "snpeOutputLayers" + name: "snpeOutputLayerName" + value { + value: "Postprocessor/BatchMultiClassNonMaxSuppression,add" + name: "snpeOutputLayerName" + } + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/ssd_mobilenet_v2_300_uint8.tflite" +} + +benchmark_setting { + benchmark_id: "LU_gpu_float32" + setting { + id: "accelerator" + name: "accelerator" + value { + value: "gpu_f16" + name: "GPU(Float 16)" + } + } + setting { + id: "configuration" + name: "Configuration" + value { + value: "QTI backend using SNPE, NNAPI and TFLite GPU Delegate" + name: "TFLite" + } + } + src: "https://github.com/mlcommons/mobile_models/raw/main/v0_7/tflite/mobilebert_float_384_gpu.tflite" +})SETTINGS"; + +#endif diff --git a/mobile_back_qti/cpp/backend_qti/rpcmem.cc b/mobile_back_qti/cpp/backend_qti/rpcmem.cc new file mode 100644 index 000000000..b8e669561 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/rpcmem.cc @@ -0,0 +1,63 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "rpcmem.h" + +#include "tensorflow/core/platform/logging.h" + +RpcMem::RpcMem() { + libHandle_ = dlopen("libadsprpc.so", RTLD_NOW); + + if (libHandle_ == nullptr) { + LOG(ERROR) << "Can't open rpc lib"; + isSuccess_ = false; + } else { + rpcmem_alloc = + reinterpret_cast(dlsym(libHandle_, "rpcmem_alloc")); + rpcmem_free = + reinterpret_cast(dlsym(libHandle_, "rpcmem_free")); + + if (rpcmem_alloc && rpcmem_free) { + isSuccess_ = true; + } else { + isSuccess_ = false; + } + + LOG(ERROR) << "Able to open rpc lib. " << isSuccess_; + } +} + +RpcMem::~RpcMem() { + isSuccess_ = false; + dlclose(libHandle_); +} + +void *RpcMem::Alloc(int id, uint32_t flags, int size) { + if (isSuccess_) { + return rpcmem_alloc(id, flags, size); + } else { + return std::malloc(size); + } +} + +void *RpcMem::Alloc(int size) { return Alloc(25, 1, size); } + +void RpcMem::Free(void *data) { + if (isSuccess_) { + return rpcmem_free(data); + } else { + return std::free(data); + } +} diff --git a/mobile_back_qti/cpp/backend_qti/rpcmem.h b/mobile_back_qti/cpp/backend_qti/rpcmem.h new file mode 100644 index 000000000..34e4192b5 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/rpcmem.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +#include +#include + +#ifndef RPCMEM_H +#define RPCMEM_H + +using RpcMemAllocPtr = std::add_pointer::type; +using RpcMemFreePtr = std::add_pointer::type; + +class RpcMem { + public: + RpcMem(); + ~RpcMem(); + void *Alloc(int heapid, uint32_t flags, int nbytes); + void *Alloc(int nbytes); + void Free(void *data); + + private: + void *libHandle_; + bool isSuccess_; + RpcMemAllocPtr rpcmem_alloc{nullptr}; + RpcMemFreePtr rpcmem_free{nullptr}; +}; + +#endif // RPCMEM_H diff --git a/mobile_back_qti/cpp/backend_qti/test.cc b/mobile_back_qti/cpp/backend_qti/test.cc new file mode 100644 index 000000000..38aa99c34 --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/test.cc @@ -0,0 +1,72 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "cpp/c/backend_c.h" +#include "cpp/c/type.h" +#include "tensorflow/lite/shared_library.h" + +void *GetSymbol(void *handle, const char *name) { + void *result; + result = tflite::SharedLibrary::GetLibrarySymbol(handle, name); + + if (!result) { + std::cout << "Unable to load symbol " << name << ": " + << tflite::SharedLibrary::GetError(); + } + return result; +} + +bool (*match)(const char **, const char **, + const mlperf_device_info_t *device_info) = nullptr; +mlperf_backend_ptr_t (*create)(const char *, mlperf_backend_configuration_t *, + const char *) = nullptr; + +int main() { + std::cout << "In main" << std::endl; + void *handle = tflite::SharedLibrary::LoadLibrary("libqtibackend.so"); + + if (handle == nullptr) { + std::cout << "Failed to load QTI backend" << std::endl; + return 1; + } + + match = reinterpret_cast( + GetSymbol(handle, "mlperf_backend_matches_hardware")); + + if (match == nullptr) { + std::cout << "Failed to load match function" << std::endl; + return 1; + } + const char *errmsg, *settings; + mlperf_device_info_t device_info = {"QRD", "Qualcomm"}; + bool rv = match(&errmsg, &settings, &device_info); + + if (!rv) { + std::cout << "HW doesn't match" << std::endl; + return 1; + } +#if 0 + create = + reinterpret_cast(GetSymbol("mlperf_backend_create")); + + const SettingList& settings; + mlperf_backend_configuration_t backend_config_ = CppToCSettings(settings); + mlperf_backend_ptr_t backendptr = create("test1.tflite", &config, "./"); + int32_t input_count = get_input_count(backend_ptr); + int32_t output_count = get_output_count(backend_ptr); +#endif +} diff --git a/mobile_back_qti/cpp/backend_qti/tflite_c.cc b/mobile_back_qti/cpp/backend_qti/tflite_c.cc new file mode 100644 index 000000000..39e5b9eba --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/tflite_c.cc @@ -0,0 +1,239 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include +#include + +#include "tensorflow/core/platform/logging.h" +#include "tensorflow/lite/c/c_api.h" +#include "tensorflow/lite/c/common.h" +#if __ANDROID__ +#include "tensorflow/lite/delegates/gpu/delegate.h" +#include "tensorflow/lite/delegates/nnapi/nnapi_delegate.h" +#endif +#include "tflite_c.h" + +void tflite_backend_delete(mlperf_backend_ptr_t backend_ptr); + +struct TFLiteBackendData { + const char* name = "TFLite-C"; + TfLiteModel* model{nullptr}; + TfLiteInterpreterOptions* options{nullptr}; + TfLiteInterpreter* interpreter{nullptr}; + TfLiteDelegate* delegate{nullptr}; +}; + +inline mlperf_data_t::Type TfType2Type(TfLiteType type) { + switch (type) { + case kTfLiteFloat32: + return mlperf_data_t::Float32; + case kTfLiteUInt8: + return mlperf_data_t::Uint8; + case kTfLiteInt8: + return mlperf_data_t::Int8; + case kTfLiteFloat16: + return mlperf_data_t::Float16; + case kTfLiteInt32: + return mlperf_data_t::Int32; + case kTfLiteInt64: + return mlperf_data_t::Int64; + default: + printf("TfLiteType %d not supported", type); + return mlperf_data_t::Float32; + } +} + +size_t TFLiteNumElements(const TfLiteTensor* tensor) { + size_t result = 1; + for (int i = 0; i < TfLiteTensorNumDims(tensor); ++i) { + result *= TfLiteTensorDim(tensor, i); + } + return result; +} + +// Create a new backend and return the pointer to it. +mlperf_backend_ptr_t tflite_backend_create( + const char* model_path, mlperf_backend_configuration_t* configs) { + TFLiteBackendData* backend_data = new TFLiteBackendData(); + + // Load the model. + backend_data->model = TfLiteModelCreateFromFile(model_path); + if (!backend_data->model) { + LOG(FATAL) << "Failed to load model: " << model_path; + tflite_backend_delete(backend_data); + return nullptr; + } + + // Create interpreter options. + backend_data->options = TfLiteInterpreterOptionsCreate(); + std::string delegateStr = configs->accelerator; +#if __ANDROID__ + if (delegateStr == "gpu_f16") { + TfLiteGpuDelegateOptionsV2 options = + TfLiteGpuDelegateOptionsV2Default(); + options.inference_preference = + TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED; + options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY; + options.max_delegated_partitions = 1; + backend_data->delegate = TfLiteGpuDelegateV2Create(&options); + } else if (delegateStr.find("nnapi") == 0) { + auto options = tflite::StatefulNnApiDelegate::Options(); + options.allow_fp16 = false; + options.disallow_nnapi_cpu = true; + std::string accelerator_name = + (delegateStr.find("-") != std::string::npos) + ? delegateStr.substr(delegateStr.find('-') + 1) + : std::string(); + options.execution_preference = tflite::StatefulNnApiDelegate::Options:: + ExecutionPreference::kFastSingleAnswer; + if (!accelerator_name.empty()) { + options.accelerator_name = accelerator_name.c_str(); + } + backend_data->delegate = new tflite::StatefulNnApiDelegate(options); + } + if (backend_data->delegate != nullptr) { + TfLiteInterpreterOptionsAddDelegate(backend_data->options, + backend_data->delegate); + } +#endif + for (int i = 0; i < configs->count; ++i) { + if (strcmp(configs->keys[i], "num_threads") == 0) { + TfLiteInterpreterOptionsSetNumThreads(backend_data->options, + atoi(configs->values[i])); + } + } + + // Create the interpreter. + backend_data->interpreter = + TfLiteInterpreterCreate(backend_data->model, backend_data->options); + if (!backend_data->interpreter) { + LOG(FATAL) << "Failed to create the interpreter"; + tflite_backend_delete(backend_data); + return nullptr; + } + + // Allocate tensors. + if (TfLiteInterpreterAllocateTensors(backend_data->interpreter) != + kTfLiteOk) { + LOG(FATAL) << "Failed to create the interpreter"; + tflite_backend_delete(backend_data); + return nullptr; + } + + return backend_data; +} + +// Destroy the backend pointer and its data. +void tflite_backend_delete(mlperf_backend_ptr_t backend_ptr) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + delete backend_data->delegate; + TfLiteModelDelete(backend_data->model); + TfLiteInterpreterOptionsDelete(backend_data->options); + TfLiteInterpreterDelete(backend_data->interpreter); + delete backend_data; +} + +// Run the inference for a sample. +mlperf_status_t tflite_backend_issue_query(mlperf_backend_ptr_t backend_ptr) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + if (TfLiteInterpreterInvoke(backend_data->interpreter) != kTfLiteOk) { + printf("Failed to run the inference"); + return MLPERF_FAILURE; + } + return MLPERF_SUCCESS; +} + +// Flush the staged queries immediately. +mlperf_status_t tflite_backend_flush_queries(mlperf_backend_ptr_t backend_ptr) { + return MLPERF_SUCCESS; +} + +// Return the number of inputs of the model. +int32_t tflite_backend_get_input_count(mlperf_backend_ptr_t backend_ptr) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + return TfLiteInterpreterGetInputTensorCount(backend_data->interpreter); +} + +// Return the type of the ith input. +mlperf_data_t tflite_backend_get_input_type(mlperf_backend_ptr_t backend_ptr, + int32_t i) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + const TfLiteTensor* tensor = + TfLiteInterpreterGetInputTensor(backend_data->interpreter, i); + mlperf_data_t type; + type.type = TfType2Type(TfLiteTensorType(tensor)); + type.size = TFLiteNumElements(tensor); + return type; +} +// Set the data for ith input. +mlperf_status_t tflite_backend_set_input(mlperf_backend_ptr_t backend_ptr, + int32_t batchIndex, int32_t i, + void* data) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + TfLiteTensor* tensor = + TfLiteInterpreterGetInputTensor(backend_data->interpreter, i); + tensor->data.raw = (char*)data; + return MLPERF_SUCCESS; +} + +// Return the number of outputs fro the model. +int32_t tflite_backend_get_output_count(mlperf_backend_ptr_t backend_ptr) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + return TfLiteInterpreterGetOutputTensorCount(backend_data->interpreter); +} +// Return the type of ith output. +mlperf_data_t tflite_backend_get_output_type(mlperf_backend_ptr_t backend_ptr, + int32_t i) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + const TfLiteTensor* tensor = + TfLiteInterpreterGetOutputTensor(backend_data->interpreter, i); + mlperf_data_t type; + type.type = TfType2Type(TfLiteTensorType(tensor)); + type.size = TFLiteNumElements(tensor); + return type; +} + +// Get the data from ith output. +mlperf_status_t tflite_backend_get_output(mlperf_backend_ptr_t backend_ptr, + uint32_t batchIndex, int32_t i, + void** data) { + TFLiteBackendData* backend_data = (TFLiteBackendData*)backend_ptr; + const TfLiteTensor* output_tensor = + TfLiteInterpreterGetOutputTensor(backend_data->interpreter, i); + switch (output_tensor->type) { + case kTfLiteFloat32: + *data = output_tensor->data.f; + break; + case kTfLiteUInt8: + *data = output_tensor->data.uint8; + break; + case kTfLiteInt8: + *data = output_tensor->data.int8; + break; + case kTfLiteFloat16: + *data = output_tensor->data.f16; + break; + case kTfLiteInt32: + *data = output_tensor->data.i32; + break; + case kTfLiteInt64: + *data = output_tensor->data.i64; + break; + default: + printf("Data type not yet supported"); + return MLPERF_FAILURE; + } + return MLPERF_SUCCESS; +} diff --git a/mobile_back_qti/cpp/backend_qti/tflite_c.h b/mobile_back_qti/cpp/backend_qti/tflite_c.h new file mode 100644 index 000000000..da2117ecf --- /dev/null +++ b/mobile_back_qti/cpp/backend_qti/tflite_c.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#pragma once + +#include "android/cpp/c/backend_c.h" +#include "android/cpp/c/type.h" + +// Create a new backend and return the pointer to it. +mlperf_backend_ptr_t tflite_backend_create( + const char* model_path, mlperf_backend_configuration_t* configs); +// Destroy the backend pointer and its data. +void tflite_backend_delete(mlperf_backend_ptr_t backend_ptr); +// Run the inference for a sample. +mlperf_status_t tflite_backend_issue_query(mlperf_backend_ptr_t backend_ptr); +// Flush the staged queries immediately. +mlperf_status_t tflite_backend_flush_queries(mlperf_backend_ptr_t backend_ptr); +// Return the number of inputs of the model. +int32_t tflite_backend_get_input_count(mlperf_backend_ptr_t backend_ptr); +// Return the type of the ith input. +mlperf_data_t tflite_backend_get_input_type(mlperf_backend_ptr_t backend_ptr, + int32_t i); +// Set the data for ith input. +mlperf_status_t tflite_backend_set_input(mlperf_backend_ptr_t backend_ptr, + int32_t batchIndex, int32_t i, + void* data); +// Return the number of outputs fro the model. +int32_t tflite_backend_get_output_count(mlperf_backend_ptr_t backend_ptr); +// Return the type of ith output. +mlperf_data_t tflite_backend_get_output_type(mlperf_backend_ptr_t backend_ptr, + int32_t i); +// Get the data from ith output. +mlperf_status_t tflite_backend_get_output(mlperf_backend_ptr_t backend_ptr, + uint32_t batchIndex, int32_t i, + void** data); diff --git a/mobile_back_qti/datasets/Makefile b/mobile_back_qti/datasets/Makefile new file mode 100644 index 000000000..9c1eba621 --- /dev/null +++ b/mobile_back_qti/datasets/Makefile @@ -0,0 +1,49 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +include ../builddir.mk + +all: ${BUILDDIR}/datasets.stamp + +dependencies: + @[ -f "${BUILDDIR}/imagenet/downloads/LSVRC2012_img_val.tar" ] || (echo "Download imagenet validation data (LSVRC2012_img_val.tar) and move it to ${BUILDDIR}/imagenet/downloads/LSVRC2012_img_val.tar" && false) + +${BUILDDIR}/datasets.stamp: dependencies ${BUILDDIR}/ade20k/ade20k_out/.stamp \ + ${BUILDDIR}/coco/coco-out/.stamp \ + ${BUILDDIR}/imagenet/imagenet-out/.stamp + @touch $@ + +# ADE20K +${BUILDDIR}/ade20k/ade20k_out/.stamp: + @(cd ade20k && make) + +# Coco +${BUILDDIR}/coco/coco-out/.stamp: + @(cd coco && make) + +# Imagenet +${BUILDDIR}/imagenet/imagenet-out/.stamp: + @(cd imagenet && make) + +clean: + @(cd ade20k && make clean) + @(cd coco && make clean) + @(cd imagenet && make clean) + @rm ${BUILDDIR}/datasets.stamp + +clean_downloads: + @(cd ade20k && make clean_downloads) + @(cd coco && make clean_downloads) + @(cd imagenet && make clean_downloads) diff --git a/mobile_back_qti/datasets/README.md b/mobile_back_qti/datasets/README.md new file mode 100644 index 000000000..5557a45ec --- /dev/null +++ b/mobile_back_qti/datasets/README.md @@ -0,0 +1,7 @@ +# Datasets + +This Makefile will create the calibration data required for the DLCs and generate the DLCs + +The DLCs are already checked into this repo under ../java/org/mlperf/inference/assets. + +This Makefile is only to show how to re-create the DLCs. diff --git a/mobile_back_qti/datasets/ade20k/Makefile b/mobile_back_qti/datasets/ade20k/Makefile new file mode 100644 index 000000000..b4672aa90 --- /dev/null +++ b/mobile_back_qti/datasets/ade20k/Makefile @@ -0,0 +1,84 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +include ../../builddir.mk + +ADE20K_OUT=${BUILDDIR}/ade20k/ade20k_out +DOWNLOADS=${BUILDDIR}/ade20k/downloads + +all: ${ADE20K_OUT}/ade20k_image_list.txt + +include ../../docker.mk + +# Get calibration data +${DOWNLOADS}/ADE20K_2016.zip: + @echo "Fetching ADE20K_2016.zip" + @mkdir -p ${DOWNLOADS} + @echo rm -f ${DOWNLOADS}/zip.part?? + python3 ${TOPDIR}/utils/chunkdownload.py https://data.deepai.org/ADE20K_2016.zip 4051732024 ${DOWNLOADS}/zip + @cat ${DOWNLOADS}/zip.part?? > $@ + +${ADE20K_OUT}/ADE20K_2016_07_26/.stamp: ${DOWNLOADS}/ADE20K_2016.zip + @rm -rf ${ADE20K_OUT}/ADE20K_2016_07_26 + @mkdir -p ${ADE20K_OUT}/ADE20K_2016_07_26 + @echo "Extracting ADE20K_2016.zip" + @(cd ${ADE20K_OUT} && unzip -q ${DOWNLOADS}/ADE20K_2016.zip) + @touch $@ + +# Used 41a1e1d6200cebaa5cfd73ce7110998480a2f43b for testing +${DOWNLOADS}/v2.3.0.zip: + @echo "Fetching tensorflow/models" + @mkdir -p ${DOWNLOADS} + @(cd ${DOWNLOADS} && wget https://github.com/tensorflow/models/archive/v2.3.0.zip) + +${DOWNLOADS}/models-2.3.0/.stamp: ${DOWNLOADS}/v2.3.0.zip + @(cd ${DOWNLOADS} && unzip v2.3.0.zip) + @touch $@ + +${ADE20K_OUT}/quantdata.stamp: + ${DOWNLOADS}/models-2.3.0/.stamp \ + ${ADE20K_OUT}/ADE20K_2016_07_26/.stamp \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + @rm -rf ${ADE20K_OUT}/quantdata + @mkdir -p ${ADE20K_OUT}/quantdata + @docker run \ + -e PYTHONPATH=/downloads/models-2.3.0/research/slim:/downloads/models-2.3.0/research/deeplab:/downloads/models-2.3.0/research \ + -v $(CURDIR):/ade20k \ + -v ${ADE20K_OUT}:/ade20k_out \ + -v ${DOWNLOADS}:/downloads \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + python3 /ade20k/resize_512_ade20k_calibration.py /ade20k_out/ADE20K_2016_07_26 /ade20k_out/quantdata /ade20k/ade20k_calibration_files.txt + @touch $@ + +${ADE20K_OUT}/ade20k_image_list.txt: ${ADE20K_OUT}/quantdata.stamp + @echo "Generating ADE20k quantization images for SNPE" + @mkdir -p ${ADE20K_OUT}/quantdata_raw + @docker run \ + -v $(CURDIR)/..:/datasets \ + -v ${ADE20K_OUT}:/ade20k_out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "python3 /datasets/jpg_to_raw.py /ade20k_out/quantdata" + @(cd ${ADE20K_OUT}/quantdata_raw && ls > ../tmp_ade20k_image_list.txt) + @awk '{print "quantdata_raw/"$$0}' ${ADE20K_OUT}/tmp_ade20k_image_list.txt > $@ + @rm ${ADE20K_OUT}/tmp_ade20k_image_list.txt + +clean: + @rm -rf ${ADE20K_OUT} + +clean_downloads: + @rm -rf ${DOWNLOADS} + diff --git a/mobile_back_qti/datasets/ade20k/ade20k_calibration_files.txt b/mobile_back_qti/datasets/ade20k/ade20k_calibration_files.txt new file mode 100644 index 000000000..89410eaec --- /dev/null +++ b/mobile_back_qti/datasets/ade20k/ade20k_calibration_files.txt @@ -0,0 +1,500 @@ +ADE_train_00002043.jpg +ADE_train_00015805.jpg +ADE_train_00020189.jpg +ADE_train_00004245.jpg +ADE_train_00001973.jpg +ADE_train_00011792.jpg +ADE_train_00000552.jpg +ADE_train_00019113.jpg +ADE_train_00009143.jpg +ADE_train_00018960.jpg +ADE_train_00014003.jpg +ADE_train_00003813.jpg +ADE_train_00001237.jpg +ADE_train_00012129.jpg +ADE_train_00016651.jpg +ADE_train_00017026.jpg +ADE_train_00015181.jpg +ADE_train_00012573.jpg +ADE_train_00005408.jpg +ADE_train_00011105.jpg +ADE_train_00011423.jpg +ADE_train_00016146.jpg +ADE_train_00002143.jpg +ADE_train_00001424.jpg +ADE_train_00020022.jpg +ADE_train_00000469.jpg +ADE_train_00004141.jpg +ADE_train_00002198.jpg +ADE_train_00016292.jpg +ADE_train_00014604.jpg +ADE_train_00000217.jpg +ADE_train_00019434.jpg +ADE_train_00012453.jpg +ADE_train_00006873.jpg +ADE_train_00012349.jpg +ADE_train_00003623.jpg +ADE_train_00017866.jpg +ADE_train_00005688.jpg +ADE_train_00013830.jpg +ADE_train_00012735.jpg +ADE_train_00007799.jpg +ADE_train_00010459.jpg +ADE_train_00006831.jpg +ADE_train_00002580.jpg +ADE_train_00015375.jpg +ADE_train_00007478.jpg +ADE_train_00000164.jpg +ADE_train_00008901.jpg +ADE_train_00003342.jpg +ADE_train_00013943.jpg +ADE_train_00017798.jpg +ADE_train_00009969.jpg +ADE_train_00003223.jpg +ADE_train_00013689.jpg +ADE_train_00000267.jpg +ADE_train_00002548.jpg +ADE_train_00003270.jpg +ADE_train_00015991.jpg +ADE_train_00018922.jpg +ADE_train_00007878.jpg +ADE_train_00010812.jpg +ADE_train_00002096.jpg +ADE_train_00002869.jpg +ADE_train_00001799.jpg +ADE_train_00019242.jpg +ADE_train_00017069.jpg +ADE_train_00009476.jpg +ADE_train_00019649.jpg +ADE_train_00001818.jpg +ADE_train_00002131.jpg +ADE_train_00001567.jpg +ADE_train_00017183.jpg +ADE_train_00002232.jpg +ADE_train_00004610.jpg +ADE_train_00012712.jpg +ADE_train_00020094.jpg +ADE_train_00006503.jpg +ADE_train_00016594.jpg +ADE_train_00002326.jpg +ADE_train_00004542.jpg +ADE_train_00019459.jpg +ADE_train_00018617.jpg +ADE_train_00017477.jpg +ADE_train_00001934.jpg +ADE_train_00001715.jpg +ADE_train_00001022.jpg +ADE_train_00007255.jpg +ADE_train_00001937.jpg +ADE_train_00001272.jpg +ADE_train_00009473.jpg +ADE_train_00014998.jpg +ADE_train_00014609.jpg +ADE_train_00004505.jpg +ADE_train_00002312.jpg +ADE_train_00012907.jpg +ADE_train_00005860.jpg +ADE_train_00014476.jpg +ADE_train_00000065.jpg +ADE_train_00007633.jpg +ADE_train_00008005.jpg +ADE_train_00011866.jpg +ADE_train_00017462.jpg +ADE_train_00006140.jpg +ADE_train_00012554.jpg +ADE_train_00014495.jpg +ADE_train_00009823.jpg +ADE_train_00014040.jpg +ADE_train_00016613.jpg +ADE_train_00010914.jpg +ADE_train_00011277.jpg +ADE_train_00003477.jpg +ADE_train_00016121.jpg +ADE_train_00014698.jpg +ADE_train_00000479.jpg +ADE_train_00001691.jpg +ADE_train_00001792.jpg +ADE_train_00005602.jpg +ADE_train_00006974.jpg +ADE_train_00013921.jpg +ADE_train_00013492.jpg +ADE_train_00014620.jpg +ADE_train_00012186.jpg +ADE_train_00016413.jpg +ADE_train_00003559.jpg +ADE_train_00008912.jpg +ADE_train_00009170.jpg +ADE_train_00006714.jpg +ADE_train_00006445.jpg +ADE_train_00006050.jpg +ADE_train_00000537.jpg +ADE_train_00017696.jpg +ADE_train_00018621.jpg +ADE_train_00003303.jpg +ADE_train_00020197.jpg +ADE_train_00005264.jpg +ADE_train_00018902.jpg +ADE_train_00012284.jpg +ADE_train_00010264.jpg +ADE_train_00010246.jpg +ADE_train_00001259.jpg +ADE_train_00012933.jpg +ADE_train_00001525.jpg +ADE_train_00009796.jpg +ADE_train_00001634.jpg +ADE_train_00010528.jpg +ADE_train_00000044.jpg +ADE_train_00013359.jpg +ADE_train_00018167.jpg +ADE_train_00018572.jpg +ADE_train_00003667.jpg +ADE_train_00010324.jpg +ADE_train_00004015.jpg +ADE_train_00001228.jpg +ADE_train_00018762.jpg +ADE_train_00007992.jpg +ADE_train_00010224.jpg +ADE_train_00002353.jpg +ADE_train_00013168.jpg +ADE_train_00011600.jpg +ADE_train_00010553.jpg +ADE_train_00014582.jpg +ADE_train_00003437.jpg +ADE_train_00001191.jpg +ADE_train_00009766.jpg +ADE_train_00012498.jpg +ADE_train_00013774.jpg +ADE_train_00014339.jpg +ADE_train_00008760.jpg +ADE_train_00013074.jpg +ADE_train_00009496.jpg +ADE_train_00007272.jpg +ADE_train_00006073.jpg +ADE_train_00019804.jpg +ADE_train_00016909.jpg +ADE_train_00003222.jpg +ADE_train_00014764.jpg +ADE_train_00015809.jpg +ADE_train_00005284.jpg +ADE_train_00017047.jpg +ADE_train_00000003.jpg +ADE_train_00002723.jpg +ADE_train_00017400.jpg +ADE_train_00006468.jpg +ADE_train_00008826.jpg +ADE_train_00005957.jpg +ADE_train_00008831.jpg +ADE_train_00004645.jpg +ADE_train_00013124.jpg +ADE_train_00013521.jpg +ADE_train_00015644.jpg +ADE_train_00000416.jpg +ADE_train_00011685.jpg +ADE_train_00000754.jpg +ADE_train_00005455.jpg +ADE_train_00000596.jpg +ADE_train_00019589.jpg +ADE_train_00018697.jpg +ADE_train_00008106.jpg +ADE_train_00011533.jpg +ADE_train_00009102.jpg +ADE_train_00004397.jpg +ADE_train_00007336.jpg +ADE_train_00002225.jpg +ADE_train_00017852.jpg +ADE_train_00002402.jpg +ADE_train_00006198.jpg +ADE_train_00001342.jpg +ADE_train_00008351.jpg +ADE_train_00012062.jpg +ADE_train_00000533.jpg +ADE_train_00016339.jpg +ADE_train_00012696.jpg +ADE_train_00012035.jpg +ADE_train_00018654.jpg +ADE_train_00007511.jpg +ADE_train_00008525.jpg +ADE_train_00015802.jpg +ADE_train_00002325.jpg +ADE_train_00017331.jpg +ADE_train_00003549.jpg +ADE_train_00007874.jpg +ADE_train_00006400.jpg +ADE_train_00005178.jpg +ADE_train_00002300.jpg +ADE_train_00010642.jpg +ADE_train_00010959.jpg +ADE_train_00006913.jpg +ADE_train_00004184.jpg +ADE_train_00005614.jpg +ADE_train_00007019.jpg +ADE_train_00005453.jpg +ADE_train_00013654.jpg +ADE_train_00012681.jpg +ADE_train_00008103.jpg +ADE_train_00013125.jpg +ADE_train_00007143.jpg +ADE_train_00012915.jpg +ADE_train_00004834.jpg +ADE_train_00006580.jpg +ADE_train_00000230.jpg +ADE_train_00003922.jpg +ADE_train_00003882.jpg +ADE_train_00015739.jpg +ADE_train_00011888.jpg +ADE_train_00002359.jpg +ADE_train_00003336.jpg +ADE_train_00008687.jpg +ADE_train_00004113.jpg +ADE_train_00008629.jpg +ADE_train_00014863.jpg +ADE_train_00005478.jpg +ADE_train_00016289.jpg +ADE_train_00008460.jpg +ADE_train_00016895.jpg +ADE_train_00003211.jpg +ADE_train_00003675.jpg +ADE_train_00009887.jpg +ADE_train_00015367.jpg +ADE_train_00014285.jpg +ADE_train_00000277.jpg +ADE_train_00007442.jpg +ADE_train_00004440.jpg +ADE_train_00017247.jpg +ADE_train_00013007.jpg +ADE_train_00019218.jpg +ADE_train_00018754.jpg +ADE_train_00003307.jpg +ADE_train_00011660.jpg +ADE_train_00001769.jpg +ADE_train_00007612.jpg +ADE_train_00005640.jpg +ADE_train_00006960.jpg +ADE_train_00004415.jpg +ADE_train_00016586.jpg +ADE_train_00004221.jpg +ADE_train_00006120.jpg +ADE_train_00007334.jpg +ADE_train_00018299.jpg +ADE_train_00012618.jpg +ADE_train_00012536.jpg +ADE_train_00016401.jpg +ADE_train_00004091.jpg +ADE_train_00000717.jpg +ADE_train_00002725.jpg +ADE_train_00012563.jpg +ADE_train_00009147.jpg +ADE_train_00010036.jpg +ADE_train_00013780.jpg +ADE_train_00002791.jpg +ADE_train_00016284.jpg +ADE_train_00015396.jpg +ADE_train_00015287.jpg +ADE_train_00019623.jpg +ADE_train_00009655.jpg +ADE_train_00015988.jpg +ADE_train_00012397.jpg +ADE_train_00003867.jpg +ADE_train_00017354.jpg +ADE_train_00018755.jpg +ADE_train_00014717.jpg +ADE_train_00005473.jpg +ADE_train_00002781.jpg +ADE_train_00013469.jpg +ADE_train_00018100.jpg +ADE_train_00009134.jpg +ADE_train_00004665.jpg +ADE_train_00000360.jpg +ADE_train_00014286.jpg +ADE_train_00013807.jpg +ADE_train_00014689.jpg +ADE_train_00016661.jpg +ADE_train_00013273.jpg +ADE_train_00008237.jpg +ADE_train_00006266.jpg +ADE_train_00009940.jpg +ADE_train_00019122.jpg +ADE_train_00002269.jpg +ADE_train_00011839.jpg +ADE_train_00002680.jpg +ADE_train_00008163.jpg +ADE_train_00003127.jpg +ADE_train_00008180.jpg +ADE_train_00008235.jpg +ADE_train_00005587.jpg +ADE_train_00011245.jpg +ADE_train_00018624.jpg +ADE_train_00006995.jpg +ADE_train_00015008.jpg +ADE_train_00006409.jpg +ADE_train_00015705.jpg +ADE_train_00016507.jpg +ADE_train_00006115.jpg +ADE_train_00017574.jpg +ADE_train_00016868.jpg +ADE_train_00011803.jpg +ADE_train_00000446.jpg +ADE_train_00007994.jpg +ADE_train_00010870.jpg +ADE_train_00014992.jpg +ADE_train_00006369.jpg +ADE_train_00010310.jpg +ADE_train_00010276.jpg +ADE_train_00016312.jpg +ADE_train_00019752.jpg +ADE_train_00003540.jpg +ADE_train_00008825.jpg +ADE_train_00009890.jpg +ADE_train_00002319.jpg +ADE_train_00020077.jpg +ADE_train_00016731.jpg +ADE_train_00004953.jpg +ADE_train_00019510.jpg +ADE_train_00008850.jpg +ADE_train_00017129.jpg +ADE_train_00005369.jpg +ADE_train_00009103.jpg +ADE_train_00013076.jpg +ADE_train_00002687.jpg +ADE_train_00016887.jpg +ADE_train_00014241.jpg +ADE_train_00012089.jpg +ADE_train_00009642.jpg +ADE_train_00001608.jpg +ADE_train_00001309.jpg +ADE_train_00015424.jpg +ADE_train_00013341.jpg +ADE_train_00011690.jpg +ADE_train_00000740.jpg +ADE_train_00008846.jpg +ADE_train_00012560.jpg +ADE_train_00016188.jpg +ADE_train_00002215.jpg +ADE_train_00004319.jpg +ADE_train_00008925.jpg +ADE_train_00005310.jpg +ADE_train_00005951.jpg +ADE_train_00004741.jpg +ADE_train_00018795.jpg +ADE_train_00010427.jpg +ADE_train_00004906.jpg +ADE_train_00005927.jpg +ADE_train_00010169.jpg +ADE_train_00013274.jpg +ADE_train_00018657.jpg +ADE_train_00004507.jpg +ADE_train_00010389.jpg +ADE_train_00020043.jpg +ADE_train_00006884.jpg +ADE_train_00001894.jpg +ADE_train_00000337.jpg +ADE_train_00015237.jpg +ADE_train_00008041.jpg +ADE_train_00005990.jpg +ADE_train_00006839.jpg +ADE_train_00014899.jpg +ADE_train_00012758.jpg +ADE_train_00006216.jpg +ADE_train_00011820.jpg +ADE_train_00017647.jpg +ADE_train_00004005.jpg +ADE_train_00013136.jpg +ADE_train_00014840.jpg +ADE_train_00000437.jpg +ADE_train_00010198.jpg +ADE_train_00004026.jpg +ADE_train_00002093.jpg +ADE_train_00001921.jpg +ADE_train_00012941.jpg +ADE_train_00009011.jpg +ADE_train_00011846.jpg +ADE_train_00013563.jpg +ADE_train_00010011.jpg +ADE_train_00008815.jpg +ADE_train_00008864.jpg +ADE_train_00001078.jpg +ADE_train_00005293.jpg +ADE_train_00018971.jpg +ADE_train_00002292.jpg +ADE_train_00019287.jpg +ADE_train_00010206.jpg +ADE_train_00001401.jpg +ADE_train_00003077.jpg +ADE_train_00002509.jpg +ADE_train_00000213.jpg +ADE_train_00010630.jpg +ADE_train_00013891.jpg +ADE_train_00019622.jpg +ADE_train_00005843.jpg +ADE_train_00011466.jpg +ADE_train_00009748.jpg +ADE_train_00002250.jpg +ADE_train_00003474.jpg +ADE_train_00019016.jpg +ADE_train_00006529.jpg +ADE_train_00009479.jpg +ADE_train_00002860.jpg +ADE_train_00004192.jpg +ADE_train_00000138.jpg +ADE_train_00011354.jpg +ADE_train_00013855.jpg +ADE_train_00001456.jpg +ADE_train_00004149.jpg +ADE_train_00008123.jpg +ADE_train_00015138.jpg +ADE_train_00011097.jpg +ADE_train_00008199.jpg +ADE_train_00014566.jpg +ADE_train_00010973.jpg +ADE_train_00013845.jpg +ADE_train_00014219.jpg +ADE_train_00012355.jpg +ADE_train_00013302.jpg +ADE_train_00018444.jpg +ADE_train_00010519.jpg +ADE_train_00016690.jpg +ADE_train_00019808.jpg +ADE_train_00009794.jpg +ADE_train_00015588.jpg +ADE_train_00007164.jpg +ADE_train_00017813.jpg +ADE_train_00018858.jpg +ADE_train_00019448.jpg +ADE_train_00002086.jpg +ADE_train_00017566.jpg +ADE_train_00017384.jpg +ADE_train_00017363.jpg +ADE_train_00017905.jpg +ADE_train_00010331.jpg +ADE_train_00017227.jpg +ADE_train_00010461.jpg +ADE_train_00000645.jpg +ADE_train_00019295.jpg +ADE_train_00009595.jpg +ADE_train_00012888.jpg +ADE_train_00006424.jpg +ADE_train_00018988.jpg +ADE_train_00018155.jpg +ADE_train_00002913.jpg +ADE_train_00005005.jpg +ADE_train_00002006.jpg +ADE_train_00009622.jpg +ADE_train_00005802.jpg +ADE_train_00004579.jpg +ADE_train_00001322.jpg +ADE_train_00006790.jpg +ADE_train_00004770.jpg +ADE_train_00018776.jpg +ADE_train_00019184.jpg +ADE_train_00015891.jpg +ADE_train_00014932.jpg +ADE_train_00010495.jpg +ADE_train_00003617.jpg +ADE_train_00012220.jpg +ADE_train_00003214.jpg +ADE_train_00011315.jpg +ADE_train_00000541.jpg +ADE_train_00003320.jpg +ADE_train_00005388.jpg +ADE_train_00008533.jpg +ADE_train_00018939.jpg diff --git a/mobile_back_qti/datasets/ade20k/resize_512_ade20k.py b/mobile_back_qti/datasets/ade20k/resize_512_ade20k.py new file mode 100755 index 000000000..4d0fa10c2 --- /dev/null +++ b/mobile_back_qti/datasets/ade20k/resize_512_ade20k.py @@ -0,0 +1,43 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +import os +import sys +import tensorflow as tf +import deeplab.input_preprocess +from PIL import Image as Image + +tf.enable_eager_execution() + +ADE20K_PATH = sys.argv[1] +OUTPUT_PATH = sys.argv[2] + + +for i in range(1, 2001): + image_jpeg = ADE20K_PATH + '/images/validation/ADE_val_0000%04d.jpg' % i + label_png = ADE20K_PATH + '/annotations/validation/ADE_val_0000%04d.png' % i + print(image_jpeg) + image_jpeg_data = tf.io.read_file(image_jpeg) + image_tensor = tf.io.decode_jpeg(image_jpeg_data) + label_png_data = tf.io.read_file(label_png) + label_tensor = tf.io.decode_jpeg(label_png_data) + o_image, p_image, p_label = deeplab.input_preprocess.preprocess_image_and_label(image_tensor, label_tensor, 512, 512, 512, 512, is_training=False) + + target_image_jpeg = OUTPUT_PATH + '/images/ADE_val_0000%04d.jpg' % i + target_label_raw = OUTPUT_PATH + '/annotations/ADE_val_0000%04d.raw' % i + + resized_image = Image.fromarray(tf.reshape(tf.cast(p_image, tf.uint8), [512, 512, 3]).numpy()) + resized_image.save(target_image_jpeg) + tf.reshape(tf.cast(p_label, tf.uint8), [512, 512]).numpy().tofile(target_label_raw) diff --git a/mobile_back_qti/datasets/ade20k/resize_512_ade20k_calibration.py b/mobile_back_qti/datasets/ade20k/resize_512_ade20k_calibration.py new file mode 100755 index 000000000..304f6e242 --- /dev/null +++ b/mobile_back_qti/datasets/ade20k/resize_512_ade20k_calibration.py @@ -0,0 +1,47 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +import os +import sys +import fnmatch +import tensorflow as tf +import deeplab.input_preprocess +from PIL import Image as Image + +tf.enable_eager_execution() + +ADE20K_PATH = sys.argv[1] +OUTPUT_PATH = sys.argv[2] +FILELIST = sys.argv[3] + +files = open(FILELIST).read().split("\n")[:-1] +for fname in files: + print(fname) + found = False + for dirpath, dirs, files in os.walk(ADE20K_PATH): + for filename in files: + if filename == fname: + image_jpeg = os.path.join(dirpath,filename) + print(image_jpeg) + image_jpeg_data = tf.io.read_file(image_jpeg) + image_tensor = tf.io.decode_jpeg(image_jpeg_data) + o_image, p_image, p_label = deeplab.input_preprocess.preprocess_image_and_label(image_tensor, None, 512, 512, 512, 512, is_training=False) + target_image_jpeg = os.path.join(OUTPUT_PATH,fname); + resized_image = Image.fromarray(tf.reshape(tf.cast(p_image, tf.uint8), [512, 512, 3]).numpy()) + resized_image.save(target_image_jpeg) + found = True + break + if found: + break diff --git a/mobile_back_qti/datasets/coco/Makefile b/mobile_back_qti/datasets/coco/Makefile new file mode 100644 index 000000000..256491553 --- /dev/null +++ b/mobile_back_qti/datasets/coco/Makefile @@ -0,0 +1,88 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +include ../../builddir.mk + +COCO_OUT=${BUILDDIR}/coco/coco_out +DOWNLOADS=${BUILDDIR}/coco/downloads + +all: ${COCO_OUT}/.stamp + +include ../../docker.mk + +${DOWNLOADS}/val2014.zip: + @mkdir -p ${DOWNLOADS} + @echo "Fetching Coco val2014.zip" + @echo rm -f ${DOWNLOADS}/zip.part?? + @python3 ${TOPDIR}/utils/chunkdownload.py http://images.cocodataset.org/zips/val2014.zip 6645013297 ${DOWNLOADS}/zip + @cat ${DOWNLOADS}/zip.part?? > $@ + +# 2014 images are used for calibration +${COCO_OUT}/orig/val2014.stamp: ${DOWNLOADS}/val2014.zip + @rm -rf ${COCO_OUT}/orig/val2014 + @mkdir -p ${COCO_OUT}/orig + @(cd ${COCO_OUT}/orig && unzip -q ${DOWNLOADS}/val2014.zip) + @touch $@ + +${DOWNLOADS}/coco_cal_images_list.txt: + @mkdir -p ${DOWNLOADS} + @curl -o $@ -L https://raw.githubusercontent.com/mlperf/inference/master/calibration/COCO/coco_cal_images_list.txt + +# Create scaled images used for calibration +# ${COCO_OUT}/calibration/val2014 has the rescaled calibration images +${COCO_OUT}/calibration/val2014.stamp: \ + ${DOWNLOADS}/coco_cal_images_list.txt \ + ${COCO_OUT}/orig/val2014.stamp \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + @echo "Scaling Coco images to 320x320" + @rm -rf ${COCO_OUT}/calibration + @mkdir -p ${COCO_OUT}/calibration + @docker run \ + -v ${COCO_OUT}:/coco-out \ + -v $(CURDIR):/coco \ + -v ${DOWNLOADS}:/downloads \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + python3 /coco/upscale_coco.py --inputs /coco-out/orig --outputs /coco-out/calibration --size 320 320 + @touch $@ + +# Create the raw files used by SNPE for calibration/quantization +${COCO_OUT}/quantdata.stamp: \ + ${COCO_OUT}/calibration/val2014.stamp \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + @echo "Generating coco quantization data for SNPE" + @rm -rf ${COCO_OUT}/calibration/val2014_raw + @mkdir -p ${COCO_OUT}/calibration/val2014_raw + @docker run \ + -v $(CURDIR)/..:/datasets \ + -v ${COCO_OUT}:/coco_out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "python3 /datasets/jpg_to_raw.py /coco_out/calibration/val2014" + @rm -rf ${COCO_OUT}/quantdata + @mv ${COCO_OUT}/calibration/val2014_raw ${COCO_OUT}/quantdata + @(cd ${COCO_OUT}/quantdata && ls > ../tmp_coco_image_list.txt) + @(cd ${COCO_OUT} && awk '{print "quantdata/"$$0}' tmp_coco_image_list.txt > coco_image_list.txt) + @rm -f ${COCO_OUT}/tmp_coco_image_list.txt + @touch $@ + +${COCO_OUT}/.stamp: ${COCO_OUT}/quantdata.stamp + touch $@ + +clean: + @rm -rf ${COCO_OUT} + +clean_downloads: + @rm -rf ${DOWNLOADS} diff --git a/mobile_back_qti/datasets/coco/coco_cal_images_list.txt b/mobile_back_qti/datasets/coco/coco_cal_images_list.txt new file mode 100644 index 000000000..14b720d84 --- /dev/null +++ b/mobile_back_qti/datasets/coco/coco_cal_images_list.txt @@ -0,0 +1,500 @@ +000000391895.jpg +000000522418.jpg +000000184613.jpg +000000318219.jpg +000000554625.jpg +000000574769.jpg +000000060623.jpg +000000309022.jpg +000000005802.jpg +000000222564.jpg +000000118113.jpg +000000193271.jpg +000000224736.jpg +000000483108.jpg +000000403013.jpg +000000374628.jpg +000000328757.jpg +000000384213.jpg +000000293802.jpg +000000086408.jpg +000000372938.jpg +000000386164.jpg +000000223648.jpg +000000204805.jpg +000000113588.jpg +000000384553.jpg +000000337264.jpg +000000368402.jpg +000000012448.jpg +000000079841.jpg +000000515289.jpg +000000562150.jpg +000000542145.jpg +000000412151.jpg +000000579003.jpg +000000540186.jpg +000000242611.jpg +000000051191.jpg +000000269105.jpg +000000294832.jpg +000000462565.jpg +000000144941.jpg +000000173350.jpg +000000060760.jpg +000000324266.jpg +000000166532.jpg +000000360772.jpg +000000191381.jpg +000000111076.jpg +000000340559.jpg +000000258985.jpg +000000509822.jpg +000000321107.jpg +000000229643.jpg +000000125059.jpg +000000455483.jpg +000000436141.jpg +000000129001.jpg +000000232262.jpg +000000061181.jpg +000000166323.jpg +000000580041.jpg +000000326781.jpg +000000387362.jpg +000000138079.jpg +000000556616.jpg +000000472621.jpg +000000192440.jpg +000000086320.jpg +000000256668.jpg +000000383445.jpg +000000565797.jpg +000000081922.jpg +000000050125.jpg +000000364521.jpg +000000394892.jpg +000000001146.jpg +000000310391.jpg +000000097434.jpg +000000463836.jpg +000000241876.jpg +000000156832.jpg +000000270721.jpg +000000462341.jpg +000000310103.jpg +000000032992.jpg +000000122851.jpg +000000540763.jpg +000000138246.jpg +000000197254.jpg +000000032907.jpg +000000251252.jpg +000000037675.jpg +000000159537.jpg +000000268556.jpg +000000271177.jpg +000000075051.jpg +000000549399.jpg +000000085160.jpg +000000559665.jpg +000000019358.jpg +000000459912.jpg +000000015827.jpg +000000394240.jpg +000000510755.jpg +000000175831.jpg +000000079472.jpg +000000250108.jpg +000000315601.jpg +000000437218.jpg +000000503707.jpg +000000074331.jpg +000000579664.jpg +000000369763.jpg +000000199951.jpg +000000452684.jpg +000000213687.jpg +000000108094.jpg +000000527040.jpg +000000350341.jpg +000000550529.jpg +000000432176.jpg +000000281533.jpg +000000369826.jpg +000000551334.jpg +000000291380.jpg +000000368978.jpg +000000077123.jpg +000000513681.jpg +000000437370.jpg +000000078371.jpg +000000560623.jpg +000000289173.jpg +000000052759.jpg +000000568623.jpg +000000128939.jpg +000000339974.jpg +000000561100.jpg +000000150410.jpg +000000009426.jpg +000000014869.jpg +000000281221.jpg +000000440575.jpg +000000354533.jpg +000000545959.jpg +000000511058.jpg +000000091227.jpg +000000242139.jpg +000000334321.jpg +000000381021.jpg +000000170629.jpg +000000207797.jpg +000000179558.jpg +000000368117.jpg +000000015085.jpg +000000467522.jpg +000000040102.jpg +000000403020.jpg +000000006005.jpg +000000219514.jpg +000000521634.jpg +000000125476.jpg +000000402559.jpg +000000484816.jpg +000000165547.jpg +000000081561.jpg +000000227125.jpg +000000189550.jpg +000000212663.jpg +000000476005.jpg +000000505440.jpg +000000067868.jpg +000000450263.jpg +000000241691.jpg +000000450500.jpg +000000545293.jpg +000000232894.jpg +000000439969.jpg +000000029913.jpg +000000410437.jpg +000000455859.jpg +000000235302.jpg +000000431573.jpg +000000290570.jpg +000000127474.jpg +000000028758.jpg +000000163020.jpg +000000332654.jpg +000000281455.jpg +000000038029.jpg +000000017756.jpg +000000380932.jpg +000000155885.jpg +000000231408.jpg +000000305821.jpg +000000459374.jpg +000000190056.jpg +000000121041.jpg +000000156397.jpg +000000173574.jpg +000000236182.jpg +000000208589.jpg +000000334405.jpg +000000267571.jpg +000000073830.jpg +000000158952.jpg +000000082258.jpg +000000308599.jpg +000000351053.jpg +000000157269.jpg +000000495612.jpg +000000095022.jpg +000000216482.jpg +000000358342.jpg +000000008665.jpg +000000573291.jpg +000000322226.jpg +000000161470.jpg +000000452224.jpg +000000322654.jpg +000000110196.jpg +000000564563.jpg +000000093201.jpg +000000155877.jpg +000000373591.jpg +000000338948.jpg +000000084982.jpg +000000386146.jpg +000000074711.jpg +000000531854.jpg +000000015113.jpg +000000388325.jpg +000000197461.jpg +000000144053.jpg +000000271032.jpg +000000098416.jpg +000000078522.jpg +000000327807.jpg +000000134778.jpg +000000518586.jpg +000000065227.jpg +000000049633.jpg +000000476597.jpg +000000165029.jpg +000000129699.jpg +000000117125.jpg +000000007211.jpg +000000356298.jpg +000000129942.jpg +000000520433.jpg +000000183666.jpg +000000426175.jpg +000000249720.jpg +000000409009.jpg +000000554348.jpg +000000329486.jpg +000000231163.jpg +000000463633.jpg +000000383470.jpg +000000578292.jpg +000000075748.jpg +000000522778.jpg +000000365366.jpg +000000046743.jpg +000000554114.jpg +000000052644.jpg +000000269394.jpg +000000117407.jpg +000000183757.jpg +000000437609.jpg +000000434494.jpg +000000191738.jpg +000000542510.jpg +000000171500.jpg +000000146411.jpg +000000205103.jpg +000000472795.jpg +000000235006.jpg +000000182784.jpg +000000054088.jpg +000000324383.jpg +000000224861.jpg +000000319865.jpg +000000353968.jpg +000000458052.jpg +000000309852.jpg +000000480076.jpg +000000026942.jpg +000000346207.jpg +000000190767.jpg +000000490081.jpg +000000571034.jpg +000000372979.jpg +000000384204.jpg +000000089668.jpg +000000383406.jpg +000000013383.jpg +000000209692.jpg +000000205378.jpg +000000551952.jpg +000000535292.jpg +000000010694.jpg +000000143824.jpg +000000037907.jpg +000000168706.jpg +000000414679.jpg +000000486203.jpg +000000060687.jpg +000000122203.jpg +000000181449.jpg +000000171062.jpg +000000142667.jpg +000000574184.jpg +000000122390.jpg +000000099734.jpg +000000000400.jpg +000000245201.jpg +000000350694.jpg +000000419048.jpg +000000414560.jpg +000000232383.jpg +000000241453.jpg +000000178592.jpg +000000328421.jpg +000000530212.jpg +000000278166.jpg +000000457754.jpg +000000109819.jpg +000000260141.jpg +000000007682.jpg +000000540264.jpg +000000246809.jpg +000000102843.jpg +000000412914.jpg +000000440646.jpg +000000242499.jpg +000000105975.jpg +000000066800.jpg +000000511204.jpg +000000030255.jpg +000000557981.jpg +000000453819.jpg +000000260166.jpg +000000207264.jpg +000000370043.jpg +000000307936.jpg +000000458153.jpg +000000446751.jpg +000000529917.jpg +000000451872.jpg +000000031747.jpg +000000410533.jpg +000000247306.jpg +000000466774.jpg +000000420532.jpg +000000154202.jpg +000000421478.jpg +000000387173.jpg +000000516750.jpg +000000289899.jpg +000000419281.jpg +000000069946.jpg +000000109005.jpg +000000216841.jpg +000000338327.jpg +000000077184.jpg +000000291712.jpg +000000024430.jpg +000000014990.jpg +000000167854.jpg +000000032965.jpg +000000553442.jpg +000000240903.jpg +000000207056.jpg +000000476975.jpg +000000323682.jpg +000000304305.jpg +000000076460.jpg +000000468604.jpg +000000035474.jpg +000000041945.jpg +000000015690.jpg +000000102912.jpg +000000261779.jpg +000000227227.jpg +000000198448.jpg +000000122934.jpg +000000421681.jpg +000000181714.jpg +000000449981.jpg +000000573349.jpg +000000247984.jpg +000000429580.jpg +000000450247.jpg +000000329717.jpg +000000393258.jpg +000000247285.jpg +000000314154.jpg +000000579815.jpg +000000042069.jpg +000000511136.jpg +000000341393.jpg +000000299319.jpg +000000185768.jpg +000000139530.jpg +000000504142.jpg +000000288955.jpg +000000407368.jpg +000000553162.jpg +000000515779.jpg +000000262986.jpg +000000077187.jpg +000000156416.jpg +000000479057.jpg +000000563964.jpg +000000103579.jpg +000000236189.jpg +000000240028.jpg +000000062060.jpg +000000438723.jpg +000000386500.jpg +000000324937.jpg +000000557556.jpg +000000426578.jpg +000000278506.jpg +000000501762.jpg +000000370423.jpg +000000406932.jpg +000000293554.jpg +000000018149.jpg +000000289423.jpg +000000155743.jpg +000000064710.jpg +000000180447.jpg +000000318171.jpg +000000216273.jpg +000000075162.jpg +000000283210.jpg +000000252213.jpg +000000082680.jpg +000000469088.jpg +000000496768.jpg +000000562261.jpg +000000016716.jpg +000000517822.jpg +000000443591.jpg +000000344860.jpg +000000235914.jpg +000000148358.jpg +000000104025.jpg +000000062790.jpg +000000129637.jpg +000000427438.jpg +000000002684.jpg +000000256091.jpg +000000433460.jpg +000000307569.jpg +000000181962.jpg +000000120935.jpg +000000405778.jpg +000000520727.jpg +000000062151.jpg +000000353807.jpg +000000440329.jpg +000000248468.jpg +000000112085.jpg +000000379977.jpg +000000444444.jpg +000000345998.jpg +000000497312.jpg +000000143769.jpg +000000311913.jpg +000000461885.jpg +000000328289.jpg +000000318671.jpg +000000031255.jpg +000000244575.jpg +000000079380.jpg +000000175417.jpg +000000503005.jpg +000000016574.jpg +000000300814.jpg +000000316795.jpg +000000263136.jpg +000000084235.jpg +000000310177.jpg +000000227879.jpg +000000321079.jpg +000000535668.jpg +000000375840.jpg +000000466787.jpg +000000288403.jpg +000000147980.jpg +000000313789.jpg +000000121745.jpg +000000497006.jpg +000000136501.jpg +000000295589.jpg +000000037038.jpg +000000511117.jpg diff --git a/mobile_back_qti/datasets/coco/convert.sh b/mobile_back_qti/datasets/coco/convert.sh new file mode 100644 index 000000000..b6076d272 --- /dev/null +++ b/mobile_back_qti/datasets/coco/convert.sh @@ -0,0 +1,8 @@ +docker run \ + -v ${COCO_OUT}:/coco-out \ + -v $(pwd)/coco \ + -v ${DOWNLOADS}:/downloads \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_qti_backend:0.1 \ + python3 /coco/upscale_coco.py --inputs /coco-out/orig --outputs /coco-out/calibration --size 320 320 + diff --git a/mobile_back_qti/datasets/coco/upscale_coco.patch b/mobile_back_qti/datasets/coco/upscale_coco.patch new file mode 100644 index 000000000..244a4e527 --- /dev/null +++ b/mobile_back_qti/datasets/coco/upscale_coco.patch @@ -0,0 +1,11 @@ +--- upscale_coco.py 2020-09-06 17:56:20.623593943 -0700 ++++ tmp/upscale_coco.py 2020-09-06 17:54:51.788675196 -0700 +@@ -5,7 +5,7 @@ + + import cv2 + import numpy as np +-from coco import COCO ++from pycocotools.coco import COCO + + + def parse_args(): diff --git a/mobile_back_qti/datasets/coco/upscale_coco.py b/mobile_back_qti/datasets/coco/upscale_coco.py new file mode 100644 index 000000000..b7ed9a7da --- /dev/null +++ b/mobile_back_qti/datasets/coco/upscale_coco.py @@ -0,0 +1,78 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +import argparse +import json +import os +import time + +import cv2 +import numpy as np +#from pycocotools.coco import COCO + + +def parse_args(): + parser = argparse.ArgumentParser(description="Upscale COCO dataset") + parser.add_argument('--inputs', '-i', type=str, default='/coco', + help='input directory for coco dataset') + parser.add_argument('--outputs', '-o', required=True, type=str, + help='output directory for upscaled coco dataset') + parser.add_argument('--images', '-im', type=str, default='val2014', + help='image directory') + parser.add_argument('--size', required=True, type=int, nargs='+', + help='upscaled image sizes (e.g 300 300, 1200 1200') + parser.add_argument('--format', '-f', type=str, default='jpg', + help='image format') + return parser.parse_args() + + +def upscale_coco(indir, outdir, image_dir, size, fmt): + # Build directories. + print('Building directories...') + size = tuple(size) + image_in_path = os.path.join(indir, image_dir) + image_out_path = os.path.join(outdir, image_dir) + if not os.path.exists(image_out_path): + os.makedirs(image_out_path) + + # Read images. + print('Reading COCO images...') + images = open("/downloads/coco_cal_images_list.txt").read().split("\n") + + # Upscale images. + print('Upscaling images...') + for img in images: + if img == "": + continue + file_name = "COCO_val2014_"+img; + # Load, upscale, and save image. + #print("Loading %s/%s" % (image_in_path, file_name)) + image = cv2.imread(os.path.join(image_in_path, file_name)) + if len(image.shape) < 3 or image.shape[2] != 3: + # some images might be grayscale + image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB) + image = cv2.resize(image, size, interpolation=cv2.INTER_LINEAR) + cv2.imwrite(os.path.join(image_out_path, file_name[0:-3] + fmt), image) + + print('Done.') + + +def main(): + # Get arguments. + args = parse_args() + # Upscale coco. + upscale_coco(args.inputs, args.outputs, args.images, args.size, args.format) + +main() diff --git a/mobile_back_qti/datasets/imagenet/Makefile b/mobile_back_qti/datasets/imagenet/Makefile new file mode 100644 index 000000000..a64a7046a --- /dev/null +++ b/mobile_back_qti/datasets/imagenet/Makefile @@ -0,0 +1,86 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +include ../../builddir.mk + +IMAGNET_OUT=${BUILDDIR}/imagenet/imagenet_out +DOWNLOADS=${BUILDDIR}/imagenet/downloads + +all: ${IMAGNET_OUT}/.stamp + +include ../../docker.mk + +${DOWNLOADS}/LSVRC2012_img_val.tar: + @echo "ERROR: Download the imagenet validation data (LSVRC2012_img_val.tar) and place it in this directory" && false + +# TODO See if option 1 or option 2 generates better accuracy +${DOWNLOADS}/cal_image_list_option_1.txt: + curl -o $@ -L https://raw.githubusercontent.com/mlperf/inference/master/calibration/ImageNet/cal_image_list_option_1.txt + +${DOWNLOADS}/cal_image_list_option_2.txt: + curl -o $@ -L https://raw.githubusercontent.com/mlperf/inference/master/calibration/ImageNet/cal_image_list_option_2.txt + +${IMAGNET_OUT}/imagenet.stamp: \ + ${DOWNLOADS}/LSVRC2012_img_val.tar \ + ${DOWNLOADS}/cal_image_list_option_1.txt + @echo "Extracting Imagenet images for quantization" + @rm -rf ${IMAGNET_OUT}/imagenet ${IMAGNET_OUT}/orig + @mkdir -p ${IMAGNET_OUT}/imagenet + @mkdir -p ${IMAGNET_OUT}/orig + @(cd ${IMAGNET_OUT}/orig && tar xf ${DOWNLOADS}/LSVRC2012_img_val.tar) + @for f in `cat ${DOWNLOADS}/cal_image_list_option_1.txt` ; do \ + cp ${IMAGNET_OUT}/orig/$${f} ${IMAGNET_OUT}/imagenet; \ + done + @touch $@ + +${IMAGNET_OUT}/resized.stamp: \ + ${IMAGNET_OUT}/imagenet.stamp \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + @echo "Scaling Imagenet images to 224x224" + @mkdir -p ${IMAGNET_OUT}/resized + @docker run \ + -v $(CURDIR):/imagenet \ + -v ${IMAGNET_OUT}:/imagenet_out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "python3 /imagenet/Resize224.py /imagenet_out/imagenet /imagenet_out/resized" + @touch $@ + +${IMAGNET_OUT}/quantdata.stamp: \ + ${IMAGNET_OUT}/resized.stamp \ + ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + @echo "Generating Imagenet quantization data for SNPE" + @mkdir -p ${IMAGNET_OUT}/resized_raw + @docker run \ + -v $(CURDIR)/..:/datasets \ + -v ${IMAGNET_OUT}:/imagenet_out \ + -u ${USERID}:${GROUPID} \ + mlcommons/mlperf_mobile:1.0 \ + /bin/bash -c "python3 /datasets/jpg_to_raw.py /imagenet_out/resized" + @rm -rf ${IMAGNET_OUT}/quantdata + @mv ${IMAGNET_OUT}/resized_raw ${IMAGNET_OUT}/quantdata + @(cd ${IMAGNET_OUT}/quantdata && ls > ../tmp_imagenet_image_list.txt) + @(cd ${IMAGNET_OUT} && awk '{print "quantdata/"$$0}' tmp_imagenet_image_list.txt > imagenet_image_list.txt) + @rm -f ${IMAGNET_OUT}/tmp_imagenet_image_list.txt + @touch $@ + +${IMAGNET_OUT}/.stamp: ${IMAGNET_OUT}/imagenet.stamp ${IMAGNET_OUT}/quantdata.stamp + @touch $@ + +clean: + @rm -rf ${IMAGNET_OUT} + +clean_downloads: + @echo "Warning: Not removing imagenet dataset" diff --git a/mobile_back_qti/datasets/imagenet/Resize224.py b/mobile_back_qti/datasets/imagenet/Resize224.py new file mode 100644 index 000000000..05dd3ef81 --- /dev/null +++ b/mobile_back_qti/datasets/imagenet/Resize224.py @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +from PIL import Image +import os +for f in os.listdir(os.sys.argv[1]): + img = Image.open(os.sys.argv[1]+"/"+f) + img256 = img.resize((256, 256), Image.ANTIALIAS) + + # Seems like the required algo is to resize to 256x256 + # Then center crop a 224x244 image + left = (256 - 224)/2 + top = (256 - 224)/2 + right = (256 + 224)/2 + bottom = (256 + 224)/2 + + # Crop 224x224 image from the center + img224 = img256.crop((left, top, right, bottom)) + img224.save(os.sys.argv[2]+"/"+f) diff --git a/mobile_back_qti/datasets/jpg_to_raw.py b/mobile_back_qti/datasets/jpg_to_raw.py new file mode 100644 index 000000000..be54965e3 --- /dev/null +++ b/mobile_back_qti/datasets/jpg_to_raw.py @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +import os +import sys +import numpy as np +from os import listdir +from os.path import isfile, join, isdir +from io import BytesIO +from PIL import Image + +model_name = sys.argv[1] +DATA_PATH = model_name +RAW_DATA_PATH = model_name + "_raw" + +image_list = [f for f in listdir(DATA_PATH) if isfile(join(DATA_PATH, f))] +for image in image_list: + src = DATA_PATH + '/' + image + dst = RAW_DATA_PATH + '/' + image + with open(src, 'rb') as f: + jpeg_str = f.read() + original_im = Image.open(BytesIO(jpeg_str)) + converted_image = original_im.convert('RGB') + npimage = np.asarray(converted_image).astype(np.float32) + npimage = npimage * 0.00784313771874 + npimage = npimage - 1.0 + img_ndarray = np.array(npimage) + if model_name == "ade20k": + f_name = dst[:-5] + '.raw' + else : + f_name = dst[:-4] + '.raw' + npimage.astype(np.float32).tofile(f_name) diff --git a/mobile_back_qti/docker.mk b/mobile_back_qti/docker.mk new file mode 100644 index 000000000..44a670158 --- /dev/null +++ b/mobile_back_qti/docker.mk @@ -0,0 +1,29 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +.PHONY: docker_image + +${BUILDDIR}/mlperf_mobile_docker_1_0.stamp: ${APP_DIR}/android/docker/mlperf_mobile/Dockerfile + @mkdir -p ${BUILDDIR} + @docker image build -t mlcommons/mlperf_mobile:1.0 ${APPDIR}/android/docker/mlperf_mobile + @touch $@ + +${BUILDDIR}/mlperf_mobiledet_docker_image.stamp: ${TOPDIR}/docker/mlperf_mobiledet/Dockerfile + @mkdir -p ${BUILDDIR} + @docker image build -t mlcommons/mlperf_mobiledet:0.1 ${TOPDIR}/docker/mlperf_mobiledet + @touch $@ + +docker_image: ${BUILDDIR}/mlperf_mobile_docker_1_0.stamp + diff --git a/mobile_back_qti/docker/mlperf_mobiledet/Dockerfile b/mobile_back_qti/docker/mlperf_mobiledet/Dockerfile new file mode 100644 index 000000000..061dd5127 --- /dev/null +++ b/mobile_back_qti/docker/mlperf_mobiledet/Dockerfile @@ -0,0 +1,18 @@ +FROM tensorflow/tensorflow:1.15.0-py3 +LABEL maintainer="quic_mcharleb@quicinc.com" + +RUN pip3 install tf-slim scipy Pillow opencv-python setuptools matplotlib tensorflow_hub + +# Create /opt/models for github.com/tensorflow/models +RUN curl -o /opt/tensorflow_models.tar.gz -L \ + https://github.com/tensorflow/models/archive/8a064338cf811494408089e0eb9a6e274784a6f9.tar.gz \ + && tar xzf /opt/tensorflow_models.tar.gz -C /opt \ + && rm /opt/tensorflow_models.tar.gz \ + && mv /opt/models-8a064338cf811494408089e0eb9a6e274784a6f9 /opt/models + +RUN apt-get install -y --no-install-recommends protobuf-compiler + +# Compile tf_models/research protobufs +RUN ls /opt && cd /opt/models/research && protoc object_detection/protos/*.proto --python_out=. + +RUN chmod -R 777 /opt/ssdlite_mobiledet diff --git a/mobile_back_qti/qti_backend.mk b/mobile_back_qti/qti_backend.mk index acd3835db..658b6a277 100644 --- a/mobile_back_qti/qti_backend.mk +++ b/mobile_back_qti/qti_backend.mk @@ -34,8 +34,7 @@ ifeq (${WITH_QTI},1) ifneq (${SNPE_SDK},) QTI_BACKEND=--//android/java/org/mlperf/inference:with_qti="1" QTI_TARGET=//mobile_back_qti:qtibackend - # TODO: Change to backend_qti when bqckend_qti is enabled - QTI_LIB_COPY=cp output/`readlink bazel-bin`/mobile_back_qti/cpp/backend_mock_qti/libqtibackend.so output/binary/libqtibackend.so + QTI_LIB_COPY=cp output/`readlink bazel-bin`/mobile_back_qti/cpp/backend_qti/libqtibackend.so output/binary/libqtibackend.so SNPE_VERSION=$(shell basename ${SNPE_SDK}) QTI_SNPE_VERSION=$(shell grep SNPE_VERSION mobile_back_qti/variables.bzl | cut -d\" -f2) QTI_VOLUMES=-v ${SNPE_SDK}:/home/mlperf/mobile_app/mobile_back_qti/${SNPE_VERSION} diff --git a/mobile_back_qti/qti_backend_targets.mk b/mobile_back_qti/qti_backend_targets.mk new file mode 100644 index 000000000..92d584e0f --- /dev/null +++ b/mobile_back_qti/qti_backend_targets.mk @@ -0,0 +1,37 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +libqtibackend: docker_image + @echo "Building libqtibackend" + @mkdir -p output/home/mlperf/cache && chmod 777 output/home/mlperf/cache + @mkdir -p output/mobile_back_qti + @docker run \ + ${COMMON_DOCKER_FLAGS} \ + --config android_arm64 //mobile_back_qti:qtibackend + @cp output/`readlink bazel-bin`/mobile_back_qti/cpp/backend_qti/libqtibackend.so output/mobile_back_qti/libtqtibackend.so + +# You need libasan5 installed to run allocator_test (sudo apt install libasan5) +qti_allocator_test: output/mobile_back_qti/test/allocator_test +output/mobile_back_qti/test/allocator_test: docker_image + @echo "Building libqtibackend" + @mkdir -p output/home/mlperf/cache && chmod 777 output/home/mlperf/cache + @mkdir -p output/mobile_back_qti/test + @docker run \ + ${NATIVE_DOCKER_FLAGS} --experimental_repo_remote_exec \ + --config=asan \ + //mobile_back_qti/cpp/backend_qti:allocator_test + @cp output/`readlink bazel-out`/k8-opt/bin/mobile_back_qti/cpp/backend_qti/allocator_test $@ + @chmod 777 $@ + diff --git a/mobile_back_qti/third_party/BUILD.bazel b/mobile_back_qti/third_party/BUILD.bazel new file mode 100644 index 000000000..03b13394c --- /dev/null +++ b/mobile_back_qti/third_party/BUILD.bazel @@ -0,0 +1,18 @@ +# Copyright 2019 The MLPerf Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +licenses(["notice"]) # Apache 2.0 + +package(default_visibility = ["//visibility:public"]) diff --git a/mobile_back_qti/third_party/tf_grappler_cost.diff b/mobile_back_qti/third_party/tf_grappler_cost.diff new file mode 100644 index 000000000..58391ea3e --- /dev/null +++ b/mobile_back_qti/third_party/tf_grappler_cost.diff @@ -0,0 +1,19 @@ +diff --git a/tensorflow/core/grappler/costs/BUILD b/tensorflow/core/grappler/costs/BUILD +index b205f5c3e5..b64f4c7dc9 100644 +--- a/tensorflow/core/grappler/costs/BUILD ++++ b/tensorflow/core/grappler/costs/BUILD +@@ -31,7 +31,13 @@ tf_proto_library( + srcs = ["op_performance_data.proto"], + cc_api_version = 2, + make_default_target_header_only = True, +- protodeps = tf_additional_all_protos(), ++ protodeps = [ ++ "//tensorflow/core/framework:attr_value_proto", ++ "//tensorflow/core/framework:resource_handle_proto", ++ "//tensorflow/core/framework:tensor_proto", ++ "//tensorflow/core/framework:tensor_shape_proto", ++ "//tensorflow/core/protobuf:for_core_protos", ++ ], + visibility = ["//visibility:public"], + ) + diff --git a/mobile_back_qti/utils/check_size.sh b/mobile_back_qti/utils/check_size.sh new file mode 100755 index 000000000..0900fec25 --- /dev/null +++ b/mobile_back_qti/utils/check_size.sh @@ -0,0 +1,21 @@ +#!/bin/bash +########################################################################## +# Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +git rev-list --objects --all \ +| git cat-file --batch-check='%(objecttype) %(objectsize) %(objectname) %(rest)' \ +| grep "^blob" | sort --numeric-sort -k2 \ +| numfmt --field=2 --to=si diff --git a/mobile_back_qti/utils/chunkdownload.py b/mobile_back_qti/utils/chunkdownload.py new file mode 100644 index 000000000..c38538e43 --- /dev/null +++ b/mobile_back_qti/utils/chunkdownload.py @@ -0,0 +1,35 @@ +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +import os + +url=os.sys.argv[1] +numbytes=int(os.sys.argv[2]) +prefix=os.sys.argv[3] + +tokenstr = "" +if len(os.sys.argv) > 4 and os.sys.argv[4] == "usetoken": + tokenstr = '-H "Authorization: token ${GITHUB_TOKEN}"' + +chunksize = 500000000 +i=0 +for x in range(0, numbytes, chunksize): + if x+chunksize > numbytes: + end=numbytes + else: + end=x-1+chunksize + os.system("curl %s --range %d-%d -L %s -o %s.part%02d" % (tokenstr, x, end, url, prefix,i)) + i=i+1 + diff --git a/mobile_back_qti/utils/get_results.sh b/mobile_back_qti/utils/get_results.sh new file mode 100755 index 000000000..bf4f2993c --- /dev/null +++ b/mobile_back_qti/utils/get_results.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright (c) 2020-2021 Qualcomm Innovation Center, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +########################################################################## + +set -e + +if [ ! $# = 1 ]; then + echo "Usage: $0 assetsdir" + exit 1 +fi + +ASSETS=$1 + +mkdir -p ${ASSETS} + +adb pull /sdcard/Android/data/org.mlperf.inference/files/mlperf/results.json ${ASSETS}/results.json +adb pull /sdcard/Android/data/org.mlperf.inference/files/log_performance ${ASSETS}/log_performance +adb pull /sdcard/Android/data/org.mlperf.inference/files/log_accuracy ${ASSETS}/log_accuracy +