diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 0000000000000000000000000000000000000000..51b255edab9c1bb72df4c7b52e4cca31f15806eb --- /dev/null +++ b/.bazelrc @@ -0,0 +1,32 @@ +import tools/bazel.rc + +build --action_env TF_NEED_OPENCL_SYCL="0" +build --action_env TF_NEED_ROCM="0" +build --action_env TF_NEED_CUDA="0" +build --action_env TF_DOWNLOAD_CLANG="0" +#build --action_env PATH="/opt/buildtools/gcc-7.3.0/bin:/bin:/usr/bin" +#build --action_env GCC_HOST_COMPILER_PATH="/opt/buildtools/gcc-7.3.0/bin/gcc" +build:opt --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=0 +#build:opt --copt=-march=native +#build:opt --host_copt=-march=native +build:opt --define with_default_optimizations=true +build:v2 --define=tf_api_version=2 + +build:opt --copt=-ftrapv +build:opt --copt=-D_FORTIFY_SOURCE=2 +#build:opt --strip=always +build:opt --linkopt=-Wl,--strip-all + +build --subcommands +build --verbose_failures +build --sandbox_debug +build --incompatible_strict_action_env +build --nocheck_visibility + + +# build --experimental_enable_repo_mapping +# build --nocheck_visibility +# build --distinct_host_configuration=false + + +build:opt --copt="-fpic" \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 43646994074aaa5bc5546e8435dd0064ff270f8c..6489b4f98323180f49aaf53585a479e423b14616 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,53 +1,162 @@ -cmake_minimum_required(VERSION 3.14) -project(TFAdapter) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_C_FLAGS "-O2 -Wall -fPIC -fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -pipe ${CMAKE_C_FLAGS}") -set(CMAKE_CXX_FLAGS "-std=c++17 -O2 -Wall -fPIC -fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -pipe ${CMAKE_CXX_FLAGS}") - -include(${CMAKE_CURRENT_LIST_DIR}/cmake/nlohmann_json.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/cmake/secure_c.cmake) -include(${CMAKE_CURRENT_LIST_DIR}/cmake/tensorflow.cmake) -include_directories(${CMAKE_CURRENT_LIST_DIR}) -include_directories(${CMAKE_CURRENT_LIST_DIR}/inc) -include_directories(${CMAKE_CURRENT_LIST_DIR}/inc/external) -include_directories(${CMAKE_CURRENT_LIST_DIR}/inc/soft_dp) - -if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/tools/COMPILE_FLAGS OR NOT EXISTS - ${CMAKE_CURRENT_LIST_DIR}/tools/LINK_FLAGS OR NOT EXISTS - ${CMAKE_CURRENT_LIST_DIR}/tools/PYTHON_BIN_PATH OR NOT EXISTS - ${CMAKE_CURRENT_LIST_DIR}/tools/SWIG_BIN_PATH) - message(FATAL_ERROR "No validate configuration found. Did you forget to configure first?") -endif () - -file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/COMPILE_FLAGS" COMPILE_FLAGS) -file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/LINK_FLAGS" LINK_FLAGS) -file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/PYTHON_BIN_PATH" PYTHON_BIN_PATH) -file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/SWIG_BIN_PATH" SWIG_BIN_PATH) - -file(COPY ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/python DESTINATION ${CMAKE_BINARY_DIR}/dist) -file(COPY ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/swig DESTINATION ${CMAKE_BINARY_DIR}/dist) -execute_process(COMMAND ${SWIG_BIN_PATH} -python -c++ -threads ${CMAKE_BINARY_DIR}/dist/swig/ge_plugin.i) -file(COPY ${CMAKE_BINARY_DIR}/dist/swig/tf_adapter.py DESTINATION ${CMAKE_BINARY_DIR}/dist/python/npu_bridge) - -file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/*.cc) -add_library(_tf_adapter SHARED ${SOURCES} ${CMAKE_BINARY_DIR}/dist/swig/ge_plugin_wrap.cxx) - -foreach (COMPILE_FLAG ${COMPILE_FLAGS}) - target_compile_options(_tf_adapter PUBLIC "${COMPILE_FLAG}") -endforeach (COMPILE_FLAG) - -target_link_libraries(_tf_adapter PUBLIC "dl") -foreach (LINK_FLAG ${LINK_FLAGS}) - target_link_libraries(_tf_adapter PUBLIC "${LINK_FLAG}") -endforeach (LINK_FLAG) - -set_target_properties(_tf_adapter PROPERTIES PREFIX "") - -set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/dist/python/npu_bridge) - -add_custom_command(TARGET _tf_adapter - POST_BUILD - COMMAND cd ${CMAKE_BINARY_DIR}/dist/python/ && ${PYTHON_BIN_PATH} setup.py bdist_wheel - VERBATIM - ) +option(ENABLE_OPEN_SRC "Enable graphengine compile in opensource." FALSE) +if (ENABLE_OPEN_SRC) + cmake_minimum_required(VERSION 3.14) + project(TFAdapter) + + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_C_FLAGS "-O2 -Wall -fPIC -fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -pipe ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-std=c++17 -O2 -Wall -fPIC -fstack-protector-all -Wl,-z,relro,-z,now,-z,noexecstack -pipe ${CMAKE_CXX_FLAGS}") + + include(${CMAKE_CURRENT_LIST_DIR}/cmake/nlohmann_json.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake/secure_c.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/cmake/tensorflow.cmake) + include_directories(${CMAKE_CURRENT_LIST_DIR}) + include_directories(${CMAKE_CURRENT_LIST_DIR}/inc) + include_directories(${CMAKE_CURRENT_LIST_DIR}/inc/external) + include_directories(${CMAKE_CURRENT_LIST_DIR}/inc/soft_dp) + + if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/tools/COMPILE_FLAGS OR NOT EXISTS + ${CMAKE_CURRENT_LIST_DIR}/tools/LINK_FLAGS OR NOT EXISTS + ${CMAKE_CURRENT_LIST_DIR}/tools/PYTHON_BIN_PATH OR NOT EXISTS + ${CMAKE_CURRENT_LIST_DIR}/tools/SWIG_BIN_PATH) + message(FATAL_ERROR "No validate configuration found. Did you forget to configure first?") + endif () + + file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/COMPILE_FLAGS" COMPILE_FLAGS) + file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/LINK_FLAGS" LINK_FLAGS) + file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/PYTHON_BIN_PATH" PYTHON_BIN_PATH) + file(STRINGS "${CMAKE_CURRENT_LIST_DIR}/tools/SWIG_BIN_PATH" SWIG_BIN_PATH) + + file(COPY ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/python DESTINATION ${CMAKE_BINARY_DIR}/dist) + file(COPY ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/swig DESTINATION ${CMAKE_BINARY_DIR}/dist) + execute_process(COMMAND ${SWIG_BIN_PATH} -python -c++ -threads ${CMAKE_BINARY_DIR}/dist/swig/ge_plugin.i) + file(COPY ${CMAKE_BINARY_DIR}/dist/swig/tf_adapter.py DESTINATION ${CMAKE_BINARY_DIR}/dist/python/npu_bridge) + + file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/*.cc) + add_library(_tf_adapter SHARED ${SOURCES} ${CMAKE_BINARY_DIR}/dist/swig/ge_plugin_wrap.cxx) + + foreach (COMPILE_FLAG ${COMPILE_FLAGS}) + target_compile_options(_tf_adapter PUBLIC "${COMPILE_FLAG}") + endforeach (COMPILE_FLAG) + + target_link_libraries(_tf_adapter PUBLIC "dl") + foreach (LINK_FLAG ${LINK_FLAGS}) + target_link_libraries(_tf_adapter PUBLIC "${LINK_FLAG}") + endforeach (LINK_FLAG) + + set_target_properties(_tf_adapter PROPERTIES PREFIX "") + + set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/dist/python/npu_bridge) + + add_custom_command(TARGET _tf_adapter + POST_BUILD + COMMAND cd ${CMAKE_BINARY_DIR}/dist/python/ && ${PYTHON_BIN_PATH} setup.py bdist_wheel + VERBATIM + ) +else() + get_filename_component(TOP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../.." ABSOLUTE) + set(BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(CMAKE_VERBOSE_MAKEFILE ON) + + # rewrite __FILE__ to avoid absolute path + set(CMAKE_C_COMPILE_OBJECT " -D__FILE__='\"$(subst ${CMAKE_CURRENT_SOURCE_DIR}/,,$(abspath $<))\"' -Wno-builtin-macro-redefined -o -c ") + set(CMAKE_CXX_COMPILE_OBJECT " -D__FILE__='\"$(subst ${CMAKE_CURRENT_SOURCE_DIR}/,,$(abspath $<))\"' -Wno-builtin-macro-redefined -o -c ") + + execute_process(COMMAND ${HI_PYTHON} -c "import tensorflow as tf; print(tf.sysconfig.get_lib(),end='')" + OUTPUT_VARIABLE TF_INSTALL_LIB_PATH) + + file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_LIST_DIR}/tf_adapter/*.cc) + add_library(tf_adapter SHARED + ${SOURCES} + ${BASE_DIR}/tf_adapter/util/ge_plugin_wrap.cxx + ) + + target_include_directories(tf_adapter PRIVATE + ${BASE_DIR}/ + ${TOP_DIR}/inc/ + ${TOP_DIR}/inc/external/ + ${TOP_DIR}/inc/common/ + ${TOP_DIR}/inc/soft_dp/ + ${TOP_DIR}/soft_dp/ + ${TOP_DIR}/libc_sec/include/ + ${TOP_DIR}/third_party/json/include/ + ${TOP_DIR}/third_party/tensorflow/tensorflow-1.15.0/ + ${TF_INSTALL_LIB_PATH}/include/ + # ${HI_PYTHON_INC}/ + /opt/buildtools/python3.7/include/python3.7m/ + ) + + target_compile_options(tf_adapter PUBLIC + $<$:-std=c++11> + -O2 + -DNDEBUG + -ftrapv + ) + target_compile_definitions(tf_adapter PUBLIC + _FORTIFY_SOURCE=2 + ) + + target_link_libraries(tf_adapter PUBLIC + $ + -Wl,--no-as-needed + c_sec + ge_runner + datatransfer + fmk_parser + indextransform + ${TF_INSTALL_LIB_PATH}/libtensorflow_framework.so.1 + ${TF_INSTALL_LIB_PATH}/python/_pywrap_tensorflow_internal.so + -Wl,--as-needed + ) + + # rename libtf_adapter.so to _tf_adapter.so + set_target_properties(tf_adapter + PROPERTIES + PREFIX _ + ) + ################################################################################################### + add_custom_command( + OUTPUT ${BASE_DIR}/tf_adapter/util/ge_plugin_wrap.cxx + COMMAND echo "before generate swig files" + && swig -c++ -python ${BASE_DIR}/tf_adapter/swig/ge_plugin.i + && mv ${BASE_DIR}/tf_adapter/swig/ge_plugin_wrap.cxx ${BASE_DIR}/tf_adapter/util/ + && mv ${BASE_DIR}/tf_adapter/swig/tf_adapter.py ${BASE_DIR}/tf_adapter/python/npu_bridge/ + && echo "end generate swig files" + ) + + ################################################################################################### + add_custom_target( + hw_npu_bridge_1.15.0 ALL + DEPENDS tf_adapter SoftDp ${CMAKE_CURRENT_BINARY_DIR}/npu_bridge-1.15.0-py3-none-any.whl + ) + + # package _tf_adapter.so and libSoftDp.so in npu_bridge-xxx.whl + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/npu_bridge-1.15.0-py3-none-any.whl + COMMAND echo "package whl start" + && mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/wheel + && cp -r ${BASE_DIR}/tf_adapter/python/. ${CMAKE_CURRENT_BINARY_DIR}/wheel + && cp -r ${CMAKE_CURRENT_BINARY_DIR}/_tf_adapter.so ${CMAKE_CURRENT_BINARY_DIR}/wheel/npu_bridge + && cp -r $ ${CMAKE_CURRENT_BINARY_DIR}/wheel/npu_bridge + # && cp -r ${CMAKE_CURRENT_BINARY_DIR}/../../../../../soft_dp/libSoftDp.so ${CMAKE_CURRENT_BINARY_DIR}/wheel/npu_bridge + && cd ${CMAKE_CURRENT_BINARY_DIR}/wheel + && ${HI_PYTHON} setup.py bdist_wheel >/dev/null + && cp -f dist/npu_bridge-1.15.0-py3-none-any.whl ${CMAKE_CURRENT_BINARY_DIR}/ + && echo "package whl end" + ) + + ################################################################################################### + set(INSTALL_BASE_DIR "") + set(INSTALL_LIBRARY_DIR lib) + + include(CMakePackageConfigHelpers) + + install(TARGETS tf_adapter OPTIONAL + EXPORT tfplugin-targets + LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR} + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/npu_bridge-1.15.0-py3-none-any.whl OPTIONAL + DESTINATION ${INSTALL_LIBRARY_DIR} + ) +endif() \ No newline at end of file diff --git a/WORKSPACE.tpl b/WORKSPACE.tpl new file mode 100644 index 0000000000000000000000000000000000000000..9077a0bfdfcba1c374d98c00ff99d07ad86a8678 --- /dev/null +++ b/WORKSPACE.tpl @@ -0,0 +1,60 @@ +workspace(name = "tf_adapter") + +local_repository( + name="org_tensorflow", + path="../../../tensorflow-1.15.0/", +) + +# TensorFlow depends on "io_bazel_rules_closure" so we need this here. +# Needs to be kept in sync with the same target in TensorFlow's WORKSPACE file. +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +http_archive( + name = "io_bazel_rules_closure", + sha256 = "5b00383d08dd71f28503736db0500b6fb4dda47489ff5fc6bed42557c07c6ba9", + strip_prefix = "rules_closure-308b05b2419edb5c8ee0471b67a40403df940149", + urls = [ + "file://TF_PACKAGE_PATH/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz", + "https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz", + "https://github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz", # 2019-06-13 + ], +) + +http_archive( + name = "bazel_skylib", + sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e", + urls = [ + "file://TF_PACKAGE_PATH/bazel-skylib.0.8.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/0.8.0/bazel-skylib.0.8.0.tar.gz", + ], +) # https://github.com/bazelbuild/bazel-skylib/releases + + +http_archive( + name = "com_google_protobuf", + sha256 = "e9883cbd0807eb35f9e837cf7ff1d12a7a0303fef4fffb340632c98a2bbd4e2d", + strip_prefix = "protobuf-3.8.0", + urls = [ + "file://TF_PACKAGE_PATH/v3.8.0.tar.gz", + "https://storage.googleapis.com/mirror.tensorflow.org/github.com/protocolbuffers/protobuf/archive/310ba5ee72661c081129eb878c1bbcec936b20f0.tar.gz", + "https://github.com/protocolbuffers/protobuf/archive/310ba5ee72661c081129eb878c1bbcec936b20f0.tar.gz", + ], +) + +# protobuf depends on @zlib, it has to be renamed to @zlib_archive because "zlib" is already +# defined using bind for grpc +http_archive( + name = "zlib_archive", + build_file = "@org_tensorflow//:third_party/zlib.BUILD", + sha256 = "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1", + strip_prefix = "zlib-1.2.11", + urls = [ + "file://TF_PACKAGE_PATH/zlib-1.2.11.tar.gz", + ], +) + + +load('@org_tensorflow//tensorflow:workspace.bzl', 'tf_workspace') +tf_workspace() + +load('//:workspace.bzl', 'tf_adapter_workspace') +tf_adapter_workspace() diff --git a/build.sh b/build.sh index d71fe19823a334d3aaf948f6d6442c331f8fa7a0..bad93eb32ca23a224c0e4c5b85e73634a4a4ad10 100644 --- a/build.sh +++ b/build.sh @@ -70,7 +70,7 @@ mk_dir() { build_tfadapter() { logging "Create build directory and build tfadapter" cd "${BASE_PATH}" && ./configure - CMAKE_ARGS="-DBUILD_PATH=$BUILD_PATH" + CMAKE_ARGS="-DENABLE_OPEN_SRC=True -DBUILD_PATH=$BUILD_PATH" if [[ "$GCC_PREFIX" != "" ]]; then CMAKE_ARGS="$CMAKE_ARGS -DGCC_PREFIX=$GCC_PREFIX" fi diff --git a/module.mk b/module.mk new file mode 100644 index 0000000000000000000000000000000000000000..64e52842ae7f2f98195de4c965b1bd4084d57c8f --- /dev/null +++ b/module.mk @@ -0,0 +1,73 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +# static check function. Just for static check. +TF_ADPTER_OUTPUT_BASE := $(PWD)/out/$(product)/host/obj/tf_adapter +TF_ADPTER_GEN_PATH := $(TF_ADPTER_OUTPUT_BASE)/genfiles +TF_ADPTER_EXEC_PATH := $(TF_ADPTER_GEN_PATH)/execroot/tf_adapter +TF_ADPTER_REL_BUILD_PATH := $(TF_ADPTER_OUTPUT_BASE)/genfiles/execroot/tf_adapter +TF_ADPTER_WORKSPACE_BASE := third_party/tensorflow/huawei_patch/tf-1.15.0/tf_plugin +TF_ADPTER_REL_WORKSPACE_BASE := $(PWD)/$(TF_ADPTER_WORKSPACE_BASE) +TF_ADPTER_LOG_PATH := $(TF_ADPTER_OUTPUT_BASE)/tf_adapter_log +define do_libtf_adapter_coverity_check + @mkdir -p ${TF_ADPTER_LOG_PATH} + @mkdir -p $(PWD)/out/$(product)/host/obj/lib + @bash ${TF_ADPTER_REL_WORKSPACE_BASE}/tools/build_wheel.sh $(PWD)/$@ $(product) \ + 2>&1 | tee $(TF_ADPTER_LOG_PATH)/obuild_libtf_adapter.log + @python ${TF_ADPTER_REL_WORKSPACE_BASE}/tools/gen_sc_makefile_bazel.py \ + $(TF_ADPTER_LOG_PATH)/obuild_libtf_adapter.log \ + ${TF_ADPTER_REL_WORKSPACE_BASE}/tools/sc_list.txt \ + $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk \ + ${TF_ADPTER_REL_WORKSPACE_BASE}/ + #static check tool does not recognize -isystem and -iquote + @sed -i "s/iquote/I/g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s/isystem/I/g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + #change relative path to full path + @sed -i "s#"\ bazel-out"#"\ $(TF_ADPTER_EXEC_PATH)/bazel-out"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"\=bazel-out"#"\=$(TF_ADPTER_EXEC_PATH)/bazel-out"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"\ external"#"\ $(TF_ADPTER_GEN_PATH)/external"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"-Iexternal"#"-I$(TF_ADPTER_GEN_PATH)/external"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"-I\ .\ "#"-I\ $(TF_ADPTER_REL_WORKSPACE_BASE)\ "#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"\ tf_adapter"#"\ ${TF_ADPTER_REL_WORKSPACE_BASE}/tf_adapter"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + @sed -i "s#"\ $(TF_ADPTER_WORKSPACE_BASE)"#"\ $(TF_ADPTER_REL_WORKSPACE_BASE)"#g" $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk + #change authority to gcc execute + @chmod 777 -R $(TF_ADPTER_REL_BUILD_PATH)/bazel-out + @make -f $(TF_ADPTER_EXEC_PATH)/Makefile_sc.mk +endef +# static check function end. + +LOCAL_SHARED_LIBRARIES := \ + libc_sec \ + libge_runner \ + libtsdclient \ + libdatatransfer \ + libfmk_parser \ + libindextransform + +LOCAL_SOFT_DP_LIBRARIES := libSoftDp + +npu_bridge_shared_libraries := \ +$(addprefix $(HOST_OUT_INTERMEDIATE_LIBRARIES)/, \ +$(addsuffix $(TARGET_SHLIB_SUFFIX), \ +$(LOCAL_SHARED_LIBRARIES) \ +$(LOCAL_SOFT_DP_LIBRARIES))) \ + +.PHONY: $(HOST_OUT_ROOT)/npu_bridge-1.15.0-py3-none-any.whl +$(HOST_OUT_ROOT)/npu_bridge-1.15.0-py3-none-any.whl:$(npu_bridge_shared_libraries) + @mkdir -p $(dir $@) +ifeq ($(COVERITY), true) + $(call do_libtf_adapter_coverity_check) +else ifeq ($(OBB_PRINT_CMD), true) + $(call do_libtf_adapter_coverity_check) +else + @swig -c++ -python -threads $(TF_ADPTER_REL_WORKSPACE_BASE)/tf_adapter/swig/ge_plugin.i + @mv $(TF_ADPTER_REL_WORKSPACE_BASE)/tf_adapter/swig/ge_plugin_wrap.cxx $(TF_ADPTER_REL_WORKSPACE_BASE)/tf_adapter/util/ + @mv $(TF_ADPTER_REL_WORKSPACE_BASE)/tf_adapter/swig/tf_adapter.py $(TF_ADPTER_REL_WORKSPACE_BASE)/tf_adapter/python/npu_bridge/ + @bash $(PWD)/third_party/tensorflow/huawei_patch/tf-1.15.0/tf_plugin/tools/build_wheel.sh $(PWD)/$@ $(product) +endif + +LOCAL_MODULE := hw_npu_bridge_1.15.0 +.PHONY: $(LOCAL_MODULE) +$(LOCAL_MODULE):$(HOST_OUT_ROOT)/npu_bridge-1.15.0-py3-none-any.whl + +include $(BUILD_HOST_SHARED_LIBRARY) diff --git a/tf_adapter/exported_symbols.lds b/tf_adapter/exported_symbols.lds new file mode 100644 index 0000000000000000000000000000000000000000..846ce15e7f050ff1fd2b314cdd8f258c48b742a6 --- /dev/null +++ b/tf_adapter/exported_symbols.lds @@ -0,0 +1,4 @@ +tensorflow { + local: + *; +}; \ No newline at end of file diff --git a/tf_adapter/interface_checker/check_interface.py b/tf_adapter/interface_checker/check_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..dc1b5232e0af25ad6d77dba02743a631be58690a --- /dev/null +++ b/tf_adapter/interface_checker/check_interface.py @@ -0,0 +1,534 @@ +""" + check interface +""" +import os +# 获取接口规范的目录 +specs_dir = os.path.realpath("../interface_spec") +# 获取tf-adapter的根目录 +tf_adapter_root = os.path.realpath("../") + +class FuncIntfSpec: + """ + 函数API的规格定义,主要包含函数的名称,与函数的入参 + 暂时校验不了出参 + """ + def __init__(self, func_name, param_list): + self.func_name = func_name + self.param_list = param_list + self.class_list = {} + self.func_list = {} + + def add_func_spec(self, func_info): + self.func_list[func_info.func_name] = func_info + + def add_class_spec(self, spec): + self.class_list[spec.class_name]=spec + + def print_detail(self): + print("func name: %s, param_list: [%s]" % (self.func_name, ",".join(self.param_list))) + +class GlobalVarSpec: + """ + 全局变量定义,例如elewise_compute接口中的NAME_INDEX + 类型主要包含:全局变量名,全局变量值 + """ + def __init__(self, name, values): + self.global_var_name = name + self.global_var_values = values + self.func_list = {} + self.param_list = {} + +class ClassIntfSpec: + """ + class 类型的接口规格定义,例如Tik的各种API都是封装在类中的 + 类型主要包含:类的名称,类的父类,类提供的api函数接口 + """ + def __init__(self, name, supper_classes): + self.class_name = name + self.supper_classes = supper_classes + self.func_list = {} + self.param_list = {} + self.class_list = {} + + def add_func_spec(self, func_info: FuncIntfSpec): + self.func_list[func_info.func_name] = func_info + + def add_class_spec(self, spec): + self.class_list[spec.class_name]=spec + + def print_detail(self): + print("-------------------------------------------") + print("class name: %s, supper classes: %s" % (self.class_name, ",".join(self.supper_classes))) + print("func list:") + for (idx, func_spec) in self.func_list.items(): + func_spec.print_detail() + print("params list:") + for param_spec in self.param_list: + param_spec.print_detail() + print("-------------------------------------------") + + +class FileSpec: + """ + 文件的规格定义,对应到一个源码文件 + """ + def __init__(self, spec_file_name, source_file_name=""): + self.spec_file_name = spec_file_name + self.source_file_name = source_file_name + self.class_specs = {} + self.func_specs = {} + self.global_var_spec = {} + + def add_class_spec(self, spec: ClassIntfSpec): + self.class_specs[spec.class_name]=spec + + def add_func_spec(self, spec: FuncIntfSpec): + self.func_specs[spec.func_name]=spec + + def add_global_var_spec(self, spec: GlobalVarSpec): + self.global_var_spec[spec.global_var_name] = spec + + def print_detail(self): + print("===========================================") + print("file name: %s" % self.spec_file_name) + print("class specs:") + for _, class_spec in self.class_specs.items(): + class_spec.print_detail() + print("func specs:") + for _, func_spec in self.func_specs.items(): + func_spec.print_detail() + print("===========================================") + +last_tree_idx = 1 +last_tab_str = " " + +def get_tree_idx(str_info: str): + """ + python 代码的层级靠缩进来保证,这里获取缩进了几层。 + python代码的缩进其实没有规定多大,只要同一层次的缩进是一样的就可以。 + 这里假定我们的代码格式是规范的,按照4/2个空格来做 + """ + global last_tab_str + if str_info.startswith(last_tab_str): + return 1 + get_tree_idx(str_info[len(last_tab_str):]) + else: + return 1 + +def get_tree_idx_2(str_info: str): + """ + 按照2个空格来计算 + """ + TAB_STR = " " + if str_info.startswith(TAB_STR): + return 1 + get_tree_idx_2(str_info[2:]) + else: + return 1 + +def get_tree_idx_final(str_info: str): + global last_tree_idx + global last_tab_str + if last_tree_idx == 1: + if get_tree_idx_2(str_info) > 2: + last_tab_str = " " + else: + last_tab_str = " " + last_tree_idx = get_tree_idx(str_info) + return last_tree_idx + + +def build_file_spec(spec_lines, file_spec: FileSpec): + """ + 根据文件中的代码解析出规格定义。 + """ + spec_tree = [file_spec, ] + for spec_line in spec_lines: + spec_line = spec_line.rstrip() + if spec_line.startswith("#"): + continue + elif "class " in spec_line and "class _" not in spec_line: + # 表示定义了一个class + tree_idx = get_tree_idx_final(spec_line) + if "(" in spec_line: + class_name = spec_line[6:spec_line.index("(")] + super_classes = spec_line[spec_line.index("(")+1: spec_line.index(")")].split(",") + else: + class_name = spec_line[6:-1] + super_classes = [] + class_spec = ClassIntfSpec(class_name, super_classes) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(class_spec) + else: + spec_tree[tree_idx] = class_spec + spec_tree[tree_idx-1].add_class_spec(class_spec) + elif "def " in spec_line: + # 表示定义了一个函数api + tree_idx = get_tree_idx_final(spec_line) + spec_line = spec_line.strip() + func_name = spec_line[4:spec_line.index("(")] + param_list = [x.strip() for x in spec_line[spec_line.index("(")+1:spec_line.index(")")].split(",")] + func_spec = FuncIntfSpec(func_name, param_list) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(func_spec) + else: + spec_tree[tree_idx] = func_spec + spec_tree[tree_idx-1].add_func_spec(func_spec) + elif is_global_variable(spec_line): + tree_idx = get_tree_idx_final(spec_line) + name = spec_line[:spec_line.index("=")].rstrip() + values = spec_line[(len(name) + 3):] + global_var_spec = GlobalVarSpec(name, values) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(global_var_spec) + else: + spec_tree[tree_idx] = global_var_spec + spec_tree[tree_idx - 1].add_global_var_spec(global_var_spec) + + +def is_global_variable(spec_line): + if spec_line.startswith(" ") or spec_line.startswith(" "): + return False + if "=" not in spec_line: + return False + name = spec_line[:spec_line.index("=")].rstrip() + name_split = name.split("_") + for i in name_split: + if not i.isupper(): + return False + return True + + +def get_spec_info_list(): + # 从接口规范文件夹中,扫描出所有的接口规范定义 + def _get_class_spec_info(spec_line, spec_tree): + tree_idx = get_tree_idx_final(spec_line) + if "(" in spec_line: + class_name = spec_line[6:spec_line.index("(")] + super_classes = spec_line[spec_line.index("(") + 1: spec_line.index(")")].split(",") + else: + class_name = spec_line[6:-1] + super_classes = [] + class_spec = ClassIntfSpec(class_name, super_classes) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(class_spec) + else: + spec_tree[tree_idx] = class_spec + spec_tree[tree_idx - 1].add_class_spec(class_spec) + + def _get_def_spec_info(spec_line, spec_tree): + tree_idx = get_tree_idx_final(spec_line) + spec_line = spec_line.strip() + func_name = spec_line[4:spec_line.index("(")] + param_list = [x.strip() for x in spec_line[spec_line.index("(") + 1:spec_line.index(")")].split(",")] + func_spec = FuncIntfSpec(func_name, param_list) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(func_spec) + else: + spec_tree[tree_idx] = func_spec + spec_tree[tree_idx - 1].add_func_spec(func_spec) + + def _get_global_var_spec_info(spec_line, spec_tree): + tree_idx = get_tree_idx_final(spec_line) + name = spec_line[:spec_line.index("=")].rstrip() + values = spec_line[(len(name) + 3):] + global_var_spec = GlobalVarSpec(name, values) + if len(spec_tree) < (tree_idx + 1): + spec_tree.append(global_var_spec) + else: + spec_tree[tree_idx] = global_var_spec + spec_tree[tree_idx - 1].add_global_var_spec(global_var_spec) + + specs = os.listdir(specs_dir) + file_spec_list = [] + for spec_file in specs: + spec_tree = [] + source_file_path = os.path.realpath(os.path.join(specs_dir, spec_file)) + spec_lines = get_spec_from_file(source_file_path, True) + + for spec_line in spec_lines: + spec_line = spec_line.rstrip() + if "# source file:" in spec_line: + spec_source_file = spec_line[14:].strip() + file_spec = FileSpec(spec_file, spec_source_file) + file_spec_list.append(file_spec) + if len(spec_tree) < 1: + spec_tree.append(file_spec) + else: + spec_tree[0] = file_spec + elif spec_line.startswith("#"): + continue + + elif "class " in spec_line: + _get_class_spec_info(spec_line, spec_tree) + + elif "def " in spec_line: + _get_def_spec_info(spec_line, spec_tree) + + elif is_global_variable(spec_line): + _get_global_var_spec_info(spec_line, spec_tree) + + return file_spec_list + + +def get_spec_from_file(file_path, is_defined_file=False): + with open(file_path) as ff: + lines = ff.readlines() + + def _get_new_lines(line, line_end, new_lines): + if "def " in line or "class " in line: + if not line.rstrip().endswith(":"): + line_end = False + new_lines.append(line.rstrip()) + else: + new_lines.append(line.rstrip()) + elif is_global_variable(line): + new_lines.append(line.rstrip()) + return line_end + + new_lines = [] + block_comment = False + line_end = True + for line in lines: + tmp_line = line.strip() + if block_comment: + # 前面是块状注释, 直到获取到块状注释结束符为止 + if "\"\"\"" in tmp_line: + block_comment = False + else: + if is_defined_file: + if "# source file:" in line: + new_lines.append(line) + continue + if tmp_line.startswith("#"): + continue + if "\"\"\"" in tmp_line and not tmp_line.endswith("\"\"\""): + # 包含连续的3个引号,是块状注释, 这里也比较粗暴,这里块状注释一般都是独立行的 + block_comment = True + continue + if "#" in line: + # 去除行尾注释 + line = line[:line.index("#")] + if line_end: + # 因为函数以及class申明的地方可能换行了,如果前面一个函数的定义还未结束,则继续拼接上去,去除换行 + line_end = _get_new_lines(line, line_end, new_lines) + else: + new_lines[-1]+=line.strip() + # 函数定义和class定义都是以冒号结尾的,检测冒号 + if line.rstrip().endswith(":"): + line_end = True + + return new_lines + + +def remove_sub_func_under_func(lines): + """ + 因为get_spec_from_file提取的是文件中的接口和class定义。 + 由于函数内部还可以定义函数,这里也会被提取出来,因此去除函数内部的函数。 + """ + tree_info = [""] + new_lines = [] + for line in lines: + idx = get_tree_idx_final(line) + if line.strip().startswith("def "): + type_name = "func" + elif line.strip().startswith("class "): + type_name = "class" + elif is_global_variable(line): + name = line[:line.index("=")].rstrip() + type_name = name + if type_name == "func" and tree_info[min(len(tree_info)-1, idx-1)] == "func": + continue + if len(tree_info) <= idx: + tree_info.append(type_name) + else: + tree_info[idx] = type_name + new_lines.append(line) + return new_lines + + +def check_source_file_match(defined_spec: FileSpec): + """ + 校验源码是否符合规范定义 + """ + source_file_path = os.path.realpath(os.path.join(tf_adapter_root, defined_spec.source_file_name)) + lines = get_spec_from_file(source_file_path) + new_lines = remove_sub_func_under_func(lines) + + spec_in_source = FileSpec("", source_file_path) + build_file_spec(new_lines, spec_in_source) + + return compare_file_spec(defined_spec, spec_in_source) + + +def compare_func_spec(spec1: FuncIntfSpec, spec2: FuncIntfSpec, file_name1="", file_name2=""): + params_1 = sorted([x.strip() for x in spec1.param_list]) + params_2 = sorted([x.strip() for x in spec2.param_list]) + if params_1 != params_2: + print("[EEEE] compare \"%s\" func failed" % spec1.func_name) + print("[EEEE] file path: \"%s\"" % file_name1) + print("[EEEE] param list: \"%s\"" % ",".join(params_1)) + print("[EEEE] file path: \"%s\"" % file_name2) + print("[EEEE] param list: \"%s\"" % ",".join(params_2)) + return False + else: + print("[====] compare \"%s\" func success" % spec1.func_name) + return True + + +def build_diff_list_result(func_names_1, func_names_2): + func_names_1 = func_names_1[:] + func_names_2 = func_names_2[:] + diff_print_name1 = [] + diff_print_name2 = [] + len_1 = len(func_names_1) + len_2 = len(func_names_2) + i = 0 + j = 0 + while i(tensor_ptr) << ", output" + << reinterpret_cast(output.data.get()); if (total_bytes == 0) { LOG(INFO) << "BuildOutputTensorInfo, output index:" << i << ", total_bytes is 0, continue do next. "; continue; @@ -168,7 +168,7 @@ GeOp::GeOp(OpKernelConstruction *ctx) : AsyncOpKernel(ctx), init_flag_(false), build_flag_(false), add_graph_flag_(false), sess_init_flag_(false), compute_graph_empty_(false), data_format_(""), graph_id_(0), is_initialized_graph_(false), need_iteration_(false), tf_session_(""), ge_session_(nullptr), - job_type_(""), is_host_graph_(false), is_train_graph_(false) { + job_type_(""), is_host_graph_(false), is_train_graph_(false), handle_(nullptr), tuning_api_(nullptr) { Initialize(ctx); } @@ -196,24 +196,27 @@ void GeOp::Initialize(OpKernelConstruction *ctx) { // global environment Initialize, invoke once for each process string sess_config = ""; OP_REQUIRES_OK(ctx, ctx->GetAttr("_NpuOptimizer", &sess_config)); - std::map init_options = NpuAttrs::GetInitOptions(ctx); std::map pass_options = NpuAttrs::GetPassOptions(ctx); iteration_per_loop_ = std::atoi(pass_options["iterations_per_loop"].c_str()); job_type_ = pass_options["job"]; - mstune_mode_ = init_options["ge.buildMode"]; - work_path_ = init_options["ge.tuningPath"]; - if (!mstune_mode_.empty() && !work_path_.empty()) { - handle_ = mmDlopen("libmstune_train.so", MMPA_RTLD_NOW); - OP_REQUIRES(ctx, handle_ != nullptr, errors::InvalidArgument("libmstune_train.so dlopen failed, ", mmDlerror())); - tuning_api_ = (MsTuningFunc)mmDlsym(handle_, const_cast("MsGradientTuning")); - OP_REQUIRES(ctx, tuning_api_ != nullptr, errors::InvalidArgument("dlsym MsGradientTuning API failed, ", mmDlerror())); - } if (GePlugin::GetInstance()->IsGlobal()) { LOG(INFO) << "[GEOP] GePlugin global, skip GePlugin init"; + std::map global_init_options = GePlugin::GetInstance()->GetInitOptions(); + GetMsTuneConfig(global_init_options); } else { - GePlugin::GetInstance()->Init(init_options); + std::map init_options = NpuAttrs::GetInitOptions(ctx); + GetMsTuneConfig(init_options); + GePlugin::GetInstance()->Init(init_options_); LOG(INFO) << "[GEOP] GePlugin init success"; } + + if (!mstune_mode_.empty() && !work_path_.empty()) { + handle_ = mmDlopen("libmstune_train.so", MMPA_RTLD_NOW); + OP_REQUIRES(ctx, handle_ != nullptr, errors::InvalidArgument("libmstune_train.so dlopen failed, ", mmDlerror())); + tuning_api_ = (MsTuningFunc)mmDlsym(handle_, const_cast("MsTrainTuning")); + OP_REQUIRES(ctx, tuning_api_ != nullptr, errors::InvalidArgument("dlsym MsGradientTuning API failed, ", mmDlerror())); + } + sess_options_ = NpuAttrs::GetSessOptions(ctx); init_flag_ = true; @@ -250,7 +253,7 @@ void GeOp::Finalize() { if (!GenerateReport::GetInstance()->SaveUnsupportedInfo().ok()) { LOG(WARNING) << "[GEOP] Save check report failed."; } - if (!mstune_mode_.empty() && !work_path_.empty()) { + if (handle_ != nullptr) { (void)mmDlclose(handle_); } } @@ -261,6 +264,16 @@ void GeOp::Finalize() { return; } +void GeOp::GetMsTuneConfig(std::map init_options) { + mstune_mode_ = init_options["ge.buildMode"]; + work_path_ = init_options["ge.tuningPath"]; + auto_tune_mode_ = init_options[ge::AUTO_TUNE_MODE]; + if (!mstune_mode_.empty() && !work_path_.empty()) { + init_options[ge::AUTO_TUNE_MODE] = ""; + } + init_options_ = init_options; +} + int GeOp::InitRebuildFlag(uint32_t cache_graph_id) { if (!build_flag_) { LOG(INFO) << "[GEOP] tf session " << tf_session_ << ", graph id: " << cache_graph_id @@ -573,13 +586,20 @@ void GeOp::ComputeAsync(OpKernelContext *ctx, DoneCallback done) { LOG(INFO) << "[GEOP] in tune mode, training graph handled by tools."; uint32_t device_id = 0; OP_REQUIRES_OK_ASYNC(ctx, GetEnvDeviceID(device_id), done); + LOG(INFO) << "[GEOP] in tuning func, mstune_mode_:" << mstune_mode_ + << " auto_tune_mode_:" << auto_tune_mode_; std::map tune_options = {{"work_path", work_path_}, {"job_type", mstune_mode_}, - {"devices", std::to_string(device_id)}}; + {"devices", std::to_string(device_id)}, + {"auto_tune_mode", auto_tune_mode_}}; + std::map> options; + options["mstune"] = tune_options; + options["initialize"] = init_options_; + options["session"] = sess_options_; std::vector ge_graphs; OP_REQUIRES_ASYNC(ctx, SessionManager::GetInstance().GetGeGraphs(ge_session_, ge_graphs), errors::Internal("[GEOP] ge ge session nontraining graphs failed."), done); - MsTuneStatus tune_ret = (*tuning_api_)(ge_graph, ge_graphs, ge_session_, tune_options); + MsTuneStatus tune_ret = (*tuning_api_)(ge_graph, ge_graphs, ge_session_, options); OP_REQUIRES_ASYNC(ctx, tune_ret == MSTUNE_SUCCESS, errors::Internal("[GEOP] exec msTuning func failed."), done); LOG(INFO) << "[GEOP] msTuning success."; build_flag_ = true; diff --git a/tf_adapter/kernels/geop_npu.h b/tf_adapter/kernels/geop_npu.h index f205c7be7eda795f972d61b82d9999574c349825..5d37b6ec2b55bcbdbccf03a78a44582377dc377e 100644 --- a/tf_adapter/kernels/geop_npu.h +++ b/tf_adapter/kernels/geop_npu.h @@ -43,7 +43,7 @@ limitations under the License. namespace tensorflow { using MsTuningFunc = MsTuneStatus (*)(ge::Graph &, std::vector &, ge::Session *, - std::map &); + const std::map> &); class GeOp : public AsyncOpKernel { public: explicit GeOp(OpKernelConstruction *ctx); @@ -88,6 +88,8 @@ class GeOp : public AsyncOpKernel { void GetExecGraphId(OpKernelContext *ctx, uint32_t &cache_graph_id, std::vector input_shapes); + void GetMsTuneConfig(std::map init_options); + private: static const std::string INPUT_DESC; static const std::string OUTPUT_DESC; @@ -115,6 +117,7 @@ class GeOp : public AsyncOpKernel { std::map, uint32_t> cache_graphs_; std::vector, uint32_t>> graph_counts_; std::map sess_options_; + std::map init_options_; static std::unordered_map session_and_graph_id_map_; uint32_t iteration_per_loop_; bool is_host_graph_; @@ -125,6 +128,7 @@ class GeOp : public AsyncOpKernel { bool is_train_graph_; void *handle_; MsTuningFunc tuning_api_; + string auto_tune_mode_; }; } // namespace tensorflow #endif // TENSORFLOW_KERNELS_GEOP_NPU_H_ diff --git a/tf_adapter/kernels/infeed_outfeed_ops.cc b/tf_adapter/kernels/infeed_outfeed_ops.cc index 52acf5fb674916ab92ed60b80b3910fd3cb1ff87..ef218493ab1d913c421b2458ca67cc6a9af50bbb 100644 --- a/tf_adapter/kernels/infeed_outfeed_ops.cc +++ b/tf_adapter/kernels/infeed_outfeed_ops.cc @@ -67,7 +67,7 @@ Status ConvertDataItem2Tensor(const std::vector &items, std::vect LOG(INFO) << "End of processing."; return Status::OK(); } - DataType type; + DataType type = DT_FLOAT; DataTypeFromString(item.tensorType_, &type); if (type == DT_STRING) { Tensor result_tensor(tensorflow::DT_STRING, TensorShape({})); diff --git a/tf_adapter/kernels/unique_parallel_ops.cc b/tf_adapter/kernels/unique_parallel_ops.cc index 5bb1c395d4f1a2245fa9cebb6ae3df44dbc35583..f113b67fcdd9f1e1682b37137eacca605f26523d 100755 --- a/tf_adapter/kernels/unique_parallel_ops.cc +++ b/tf_adapter/kernels/unique_parallel_ops.cc @@ -51,43 +51,40 @@ class UniqueParallelOp : public OpKernel { errors::InvalidArgument("input tensor should be int32 or int64, but got ", DataTypeString(input_tensor.dtype()))); auto input_vec = input_tensor.vec(); - + int64 total = static_cast(input_vec.size()); Tensor* index_tensor = nullptr; - OP_REQUIRES_OK(context, context->allocate_output(1, + OP_REQUIRES_OK(context, context->allocate_output(1, TensorShape({input_vec.size()}), &index_tensor)); - auto index_vec = index_tensor->template vec(); + auto index_vec = index_tensor->vec(); - const int cpu_nums = 16; + const int64 CPU_NUMS = 16; std::atomic count_num(0); - std::vector > unique_map_vec; - unique_map_vec.resize(cpu_nums); + Tensor output_temp(input_tensor.dtype(), TensorShape({total})); + auto output_temp_flat = output_temp.flat(); + tensorflow::thread::ThreadPool thread_work(context->env(), "unique_parallel", CPU_NUMS); std::function shards = [&](int64 total, int cur) { - for (TIndex i = 0; i < total; i++){ - if ((input_vec(i) & 15) == cur) { - if (unique_map_vec[cur].find(input_vec(i)) == unique_map_vec[cur].end()) { - unique_map_vec[cur][input_vec(i)] = count_num++; + std::unordered_map unique_map; + for (TIndex i = 0, j = 0; i < total; i++) { + unsigned long long temp_input = input_vec(i); + unsigned long long temp_cpu = CPU_NUMS - 1; + if ((temp_input & temp_cpu) == cur) { + if (unique_map.find(input_vec(i)) == unique_map.end()) { + j = count_num++; + unique_map[input_vec(i)] = j; + output_temp_flat(j) = input_vec(i); } - index_vec(i) = unique_map_vec[cur][input_vec(i)]; + index_vec(i) = unique_map[input_vec(i)]; } } }; - tensorflow::thread::ThreadPool thread_work(context->env(), "unique_parallel", cpu_nums); - ParallelFor(thread_work, (int64)(input_vec.size()), cpu_nums, shards); - - Tensor* output_tensor = nullptr; + ParallelFor(thread_work, total, CPU_NUMS, shards); + Tensor *output_tensor = nullptr; OP_REQUIRES_OK(context, context->allocate_output(0, TensorShape({count_num}), &output_tensor)); - auto output_vec = output_tensor->template vec(); - int index = 0; - for (size_t i = 0; i < unique_map_vec.size(); i++) { - for (auto it : unique_map_vec[i]) { - output_vec(index) = it.first; - index++; - } - } + *output_tensor = output_temp.Slice(0, count_num); } private: - void ParallelFor(tensorflow::thread::ThreadPool& thread_work, + void ParallelFor(tensorflow::thread::ThreadPool& thread_work, int64 total, const int cpu_nums, std::function& fn) { CHECK_GE(total, 0); CHECK_EQ(total, (int64)(Eigen::Index)total); diff --git a/tf_adapter/module.BUILD b/tf_adapter/module.BUILD new file mode 100644 index 0000000000000000000000000000000000000000..d11465d35a539f4addba76b47c2e8b92c220517a --- /dev/null +++ b/tf_adapter/module.BUILD @@ -0,0 +1,65 @@ +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "hdrs", + srcs = glob(["**/*.h", "**/*.hpp"]), +) + +cc_library( + name = "foo_tensorflow_hdrs", + hdrs = glob(["include/**/*"], exclude=["include/**/*.so"]), +) + +cc_library( + name = "tf_adapter_extend_hdrs", + srcs = glob([ + "framework/**/*.h", "framework/**/*.hpp", + "graph/**/*.h", "graph/**/*.hpp", + "hccl/**/*.h", "hccl/**/*.hpp", + "tdt/**/*.h", "tdt/**/*.hpp", + "runtime/**/*.h", "runtime/**/*.hpp", + "external/**/*.h", "soft_dp/**/*.h", + "mmpa/**/*.h", "toolchain/**/*.h" + ]), +) + +cc_library( + name = "tf_adapter_host_libs", + srcs = glob([ + "libc_sec.so", + "libge_runner.so", + "libdatatransfer.so", + "libfmk_parser.so", + "libindextransform.so", + "libmmpa" + ]), +) + +cc_library( + name = "installed_tensorflow_libs", + srcs = glob([ + ]), +) + +cc_library( + name = "local_nlohmann_json_lib", + hdrs = glob([ + "nlohmann/**/*.hpp", + ]), + visibility = ["//visibility:public"], + alwayslink = 1, +) + +cc_library( + name = "sec_lib", + srcs = glob([ + "**/*.h", + ]), +) + +cc_library( + name = "python_include", + srcs = glob([ + "**/*.h", + ]), +) diff --git a/tf_adapter/optimizers/dp_tf_ge_conversion_pass.cc b/tf_adapter/optimizers/dp_tf_ge_conversion_pass.cc index 5c5c2c8615b7e703fb60df6e4635ab849692e875..db11a8a9baa9a42ea223ed477fcbfde1692e87f5 100644 --- a/tf_adapter/optimizers/dp_tf_ge_conversion_pass.cc +++ b/tf_adapter/optimizers/dp_tf_ge_conversion_pass.cc @@ -426,6 +426,7 @@ Status DpTfToGEConversionPassImpl::RemoveNotSupportDataset(Graph *g, const std:: Node *node = nullptr; Node *topo_end = nullptr; for (Node *n : g->op_nodes()) { + REQUIRES_NOT_NULL(n); if (n->type_string() == "DeviceQueueDataset" && n->name() == device_queue_dataset) { LOG(INFO) << "device queue dataset node is " << n->name(); node = n; @@ -435,6 +436,7 @@ Status DpTfToGEConversionPassImpl::RemoveNotSupportDataset(Graph *g, const std:: topo_end = n; } } + REQUIRES_NOT_NULL(node); Node *end_dataset = node; std::vector delete_nodes; while (!IsMakeIteratorNode(node)) { @@ -592,6 +594,10 @@ bool DpTfToGEConversionPassImpl::RunPass(std::unique_ptr *g, FunctionLibr LOG(INFO) << "Node [" << node->name() << "] has func:"; for (const auto &func : node_funcs) { FunctionDef *fdef = fdeflib.add_function(); + if (flib->Find(func) == nullptr) { + LOG(ERROR) << "function def is nullptr"; + return false; + } *fdef = *(flib->Find(func)); } } diff --git a/tf_adapter/optimizers/om_partition_subgraphs_pass.cc b/tf_adapter/optimizers/om_partition_subgraphs_pass.cc index f07f91d3a76f2ce896f52b72d56eacf35b8a4fdc..7b0fc231d5582c4b2c5facf6e67ec678539c7ada 100644 --- a/tf_adapter/optimizers/om_partition_subgraphs_pass.cc +++ b/tf_adapter/optimizers/om_partition_subgraphs_pass.cc @@ -1302,6 +1302,7 @@ Status OMSplitter::Subgraph::BuildFunctionDef(const string &name, FunctionLibrar LOG(INFO) << func; FunctionDef *fdef = func_def_lib->add_function(); REQUIRES_NOT_NULL(fdef); + REQUIRES_NOT_NULL(library->Find(func)); *fdef = *(library->Find(func)); } string funcdefStr; diff --git a/tf_adapter/python/npu_bridge/estimator/npu/npu_config.py b/tf_adapter/python/npu_bridge/estimator/npu/npu_config.py index a411be885927435506e16a732cb08db8443c1c22..d934570f934b7f64c4048f7062be035c1e27b1ec 100644 --- a/tf_adapter/python/npu_bridge/estimator/npu/npu_config.py +++ b/tf_adapter/python/npu_bridge/estimator/npu/npu_config.py @@ -53,7 +53,12 @@ class NPURunConfig(run_config_lib.RunConfig): optypelist_for_implmode=None, dynamic_input_config=None, mstune_mode=None, - work_path=None + work_path=None, + buffer_optimize=None, + enable_small_channel=0, + fusion_switch_file=None, + enable_compress_weight=False, + compress_weight_conf=None ): """ Constructs a NPUConfig. @@ -109,6 +114,11 @@ class NPURunConfig(run_config_lib.RunConfig): mstune_mode: Optimization Task Type."1": model tune; "2": optune; "3": model tune & optune; "4": gradient split tune. work_path: Stores temporary files generated during optimization. + buffer_optimize: Whether to enable buffer optimization. + enable_small_channel: Whether to enable small channel optimization. + fusion_switch_file: Fusion switch configuration file path. + enable_compress_weight: Whether to enable global weight compression. + compress_weight_conf:Path and file name of the node list configuration file to be compressed. """ # Check iterations_per_loop. @@ -173,6 +183,11 @@ class NPURunConfig(run_config_lib.RunConfig): self._dynamic_input_config = dynamic_input_config self._mstune_mode = mstune_mode self._work_path = work_path + self._buffer_optimize = buffer_optimize + self._enable_small_channel = enable_small_channel + self._fusion_switch_file = fusion_switch_file + self._enable_compress_weight = enable_compress_weight + self._compress_weight_conf = compress_weight_conf super(NPURunConfig, self).__init__( model_dir=model_dir, diff --git a/tf_adapter/python/npu_bridge/estimator/npu/npu_estimator.py b/tf_adapter/python/npu_bridge/estimator/npu/npu_estimator.py index 9480741c0451999fbaf019b5e4f6b33c1fc511dd..285ab31a7d6f0b78a553ca29b939424ff20e6e7b 100644 --- a/tf_adapter/python/npu_bridge/estimator/npu/npu_estimator.py +++ b/tf_adapter/python/npu_bridge/estimator/npu/npu_estimator.py @@ -727,6 +727,14 @@ class NPUEstimator(estimator_lib.Estimator): if config.enable_scope_fusion_passes is not None: custom_op.parameter_map["enable_scope_fusion_passes"].s = tf.compat.as_bytes(config.enable_scope_fusion_passes) custom_op.parameter_map["enable_exception_dump"].i = config.enable_exception_dump + if config._buffer_optimize is not None: + custom_op.parameter_map["buffer_optimize"].s = tf.compat.as_bytes(config._buffer_optimize) + custom_op.parameter_map["enable_small_channel"].i = config._enable_small_channel + if config._fusion_switch_file is not None: + custom_op.parameter_map["fusion_switch_file"].s = tf.compat.as_bytes(config._fusion_switch_file) + custom_op.parameter_map["enable_compress_weight"].b = config._enable_compress_weight + if config._compress_weight_conf is not None: + custom_op.parameter_map["compress_weight_conf"].s = tf.compat.as_bytes(config._compress_weight_conf) # add profiling options to custom_op self.__load_profiling_options(config, custom_op) diff --git a/tf_adapter/python/npu_bridge/estimator/npu/npu_plugin.py b/tf_adapter/python/npu_bridge/estimator/npu/npu_plugin.py index 37dc689ecfee8d9125d85c836392b9f62f4ce56a..8f5238730dd1fdbb4562d7dc5a462808faacb86a 100644 --- a/tf_adapter/python/npu_bridge/estimator/npu/npu_plugin.py +++ b/tf_adapter/python/npu_bridge/estimator/npu/npu_plugin.py @@ -71,9 +71,7 @@ def npu_resource_init(graph_run_mode = 1, init["ge.exec.enable_exception_dump"] = str(enable_exception_dump) rank_size = os.getenv('RANK_SIZE') if int(rank_size) > 1 and mstune_mode is not None: - mstune_mode = util.check_mstune_mode(mstune_mode) - if mstune_mode == "4": - mstune_mode = "tuning" + util.check_mstune_mode(mstune_mode) init["ge.buildMode"] = str(mstune_mode) if work_path is not None: init["ge.tuningPath"] = str(util.check_path(work_path)) diff --git a/tf_adapter/python/npu_bridge/estimator/npu/util.py b/tf_adapter/python/npu_bridge/estimator/npu/util.py index 73ceaa639e8bebe1d9cbf1b18f5aa0e3e5627948..955eae2811eee147d58bdb6f4611515a7f73e785 100644 --- a/tf_adapter/python/npu_bridge/estimator/npu/util.py +++ b/tf_adapter/python/npu_bridge/estimator/npu/util.py @@ -128,7 +128,6 @@ def check_mstune_mode(mstune_mode): mstune_modes = ['1', '2', '3', '4'] if mstune_mode not in mstune_modes: raise ValueError("mstune_mode is valid, should be in ['1', '2', '3', '4']") - return mstune_mode def register_func(var_name): ops.register_proto_function( diff --git a/tf_adapter/util/ge_plugin.cc b/tf_adapter/util/ge_plugin.cc index ad598b0d6b2c2cba380e4764e93ea3df21a4f85f..c17defe565378d691b3536b640a5e8e7ac5ed501 100644 --- a/tf_adapter/util/ge_plugin.cc +++ b/tf_adapter/util/ge_plugin.cc @@ -70,7 +70,7 @@ void GePlugin::Init(std::map &init_options, bool is_gl LOG(INFO) << "[GePlugin] Ge has already initialized"; return; } - + init_options_ = init_options; const char *tf_config = std::getenv("TF_CONFIG"); int exec_hccl_flag = 1; if (tf_config != nullptr) { @@ -149,6 +149,9 @@ void GePlugin::Init(std::map &init_options, bool is_gl LOG(INFO) << "[GePlugin] precision_mode : " << init_options[ge::PRECISION_MODE]; // auto tune configuration + if (!init_options["ge.buildMode"].empty() && !init_options["ge.tuningPath"].empty()) { + init_options[ge::AUTO_TUNE_MODE] = ""; + } LOG(INFO) << "[GePlugin] auto_tune_mode : " << init_options[ge::AUTO_TUNE_MODE]; // debug configuration @@ -163,7 +166,7 @@ void GePlugin::Init(std::map &init_options, bool is_gl LOG(INFO) << "[GePlugin] job_id : " << init_options[ge::OPTION_EXEC_JOB_ID]; // mstune mode and work path - if (init_options["ge.buildMode"] == "4") { + if (!init_options["ge.buildMode"].empty()) { init_options["ge.buildMode"] = "tuning"; } LOG(INFO) << "[GePlugin] mstune mode : " << init_options["ge.buildMode"] @@ -176,7 +179,7 @@ void GePlugin::Init(std::map &init_options, bool is_gl std::this_thread::sleep_for(std::chrono::milliseconds(kFatalSleepTime)); LOG(FATAL) << "[GePlugin] Tdt host init failed, tdt error code : " << ret; } - + // ge Initialize ge::Status status = ge::GEInitialize(init_options); if (status != ge::SUCCESS) { @@ -197,6 +200,10 @@ void GePlugin::Init(std::map &init_options, bool is_gl isGlobal_ = is_global; } +std::map GePlugin::GetInitOptions() { + return init_options_; +} + void GePlugin::Finalize() { std::lock_guard lock(mutex_); if (!isInit_) { diff --git a/tf_adapter/util/ge_plugin.h b/tf_adapter/util/ge_plugin.h index e83d73cb7ec049973d215007770443cc067fb28d..08db9eca01358fb942b4c3a9b1f10b99555d54ec 100644 --- a/tf_adapter/util/ge_plugin.h +++ b/tf_adapter/util/ge_plugin.h @@ -46,6 +46,8 @@ class GePlugin { bool IsGlobal(); + std::map GetInitOptions(); + private: GePlugin(); diff --git a/tf_adapter/util/npu_attrs.cc b/tf_adapter/util/npu_attrs.cc index bec36218f3ce38da380f5727ba18da541bf64169..fca33041a7ddaeff30df61dfb4a57696d39b700d 100644 --- a/tf_adapter/util/npu_attrs.cc +++ b/tf_adapter/util/npu_attrs.cc @@ -201,6 +201,11 @@ std::map NpuAttrs::GetSessOptions(OpKernelConstruction std::string optypelist_for_implmode; string input_shape; string dynamic_dims; + std::string buffer_optimize; + std::string enable_small_channel = "0"; + std::string fusion_switch_file; + std::string enable_compress_weight = std::to_string(false); + std::string compress_weight_conf; if (ctx != nullptr && ctx->GetAttr("_NpuOptimizer", &npuOptimizer) == Status::OK()) { ctx->GetAttr("_variable_format_optimize", &variable_format_optimize); @@ -234,6 +239,11 @@ std::map NpuAttrs::GetSessOptions(OpKernelConstruction ctx->GetAttr("_optypelist_for_implmode", &optypelist_for_implmode); ctx->GetAttr("_input_shape", &input_shape); ctx->GetAttr("_dynamic_dims", &dynamic_dims); + ctx->GetAttr("_buffer_optimize", &buffer_optimize); + ctx->GetAttr("_enable_small_channel", &enable_small_channel); + ctx->GetAttr("_fusion_switch_file", &fusion_switch_file); + ctx->GetAttr("_enable_compress_weight", &enable_compress_weight); + ctx->GetAttr("_compress_weight_conf", &compress_weight_conf); } // session options @@ -253,6 +263,11 @@ std::map NpuAttrs::GetSessOptions(OpKernelConstruction sess_options[ge::OPTYPELIST_FOR_IMPLMODE] = optypelist_for_implmode; sess_options["ge.inputShape"] = input_shape; sess_options["ge.dynamicDims"] = dynamic_dims; + sess_options["ge.bufferOptimize"] = buffer_optimize; + sess_options["ge.enableSmallChannel"] = enable_small_channel; + sess_options["ge.fusionSwitchFile"] = fusion_switch_file; + sess_options["ge.enableCompressWeight"] = enable_compress_weight; + sess_options["compress_weight_conf"] = compress_weight_conf; return sess_options; } @@ -490,6 +505,11 @@ std::map NpuAttrs::GetAllAttrOptions(AttrSlice attrs) string dynamic_dims; string mstune_mode; string work_path; + std::string buffer_optimize; + std::string enable_small_channel = "0"; + std::string fusion_switch_file; + std::string enable_compress_weight = std::to_string(false); + std::string compress_weight_conf; if (attrs.Find("_NpuOptimizer") != nullptr) { do_npu_optimizer = std::to_string(true); @@ -578,6 +598,19 @@ std::map NpuAttrs::GetAllAttrOptions(AttrSlice attrs) if (attrs.Find("_dynamic_dims") != nullptr) { dynamic_dims = attrs.Find("_dynamic_dims")->s(); } if (attrs.Find("_mstune_mode") != nullptr) { mstune_mode = attrs.Find("_mstune_mode")->s(); } if (attrs.Find("_work_path") != nullptr) { work_path = attrs.Find("_work_path")->s(); } + if (attrs.Find("_buffer_optimize") != nullptr) { buffer_optimize = attrs.Find("_buffer_optimize")->s(); } + if (attrs.Find("_enable_small_channel") != nullptr) { + enable_small_channel = attrs.Find("_enable_small_channel")->s(); + } + if (attrs.Find("_fusion_switch_file") != nullptr) { + fusion_switch_file = attrs.Find("_fusion_switch_file")->s(); + } + if (attrs.Find("_enable_compress_weight") != nullptr) { + enable_compress_weight = attrs.Find("_enable_compress_weight")->s(); + } + if (attrs.Find("_compress_weight_conf") != nullptr) { + compress_weight_conf = attrs.Find("_compress_weight_conf")->s(); + } } all_options["variable_format_optimize"] = variable_format_optimize; @@ -622,6 +655,11 @@ std::map NpuAttrs::GetAllAttrOptions(AttrSlice attrs) all_options["dynamic_dims"] = dynamic_dims; all_options["mstune_mode"] = mstune_mode; all_options["work_path"] = work_path; + all_options["buffer_optimize"] = buffer_optimize; + all_options["enable_small_channel"] = enable_small_channel; + all_options["fusion_switch_file"] = fusion_switch_file; + all_options["enable_compress_weight"] = enable_compress_weight; + all_options["compress_weight_conf"] = compress_weight_conf; return all_options; } @@ -681,6 +719,11 @@ Status NpuAttrs::SetNpuOptimizerAttr(const GraphOptimizationPassOptions &options string dynamic_dims; string mstune_mode; string work_path; + std::string buffer_optimize; + int enable_small_channel = 0; + std::string fusion_switch_file; + bool enable_compress_weight = false; + std::string compress_weight_conf; const RewriterConfig &rewrite_options = options.session_options->config.graph_options().rewrite_options(); for (const auto &custom_optimizer : rewrite_options.custom_optimizers()) { @@ -806,6 +849,19 @@ Status NpuAttrs::SetNpuOptimizerAttr(const GraphOptimizationPassOptions &options (!params.count("input_shape") && params.count("dynamic_dims"))) { LOG(FATAL) << "input_shape and dynamic_dims should be paired."; } + if (params.count("buffer_optimize")) { + buffer_optimize = params.at("buffer_optimize").s(); + if (buffer_optimize != "l2_optimize" && buffer_optimize != "off_optimize") { + LOG(FATAL) << "buffer_optimize is valid, should be one of [l2_optimize, off_optimize]"; + } + } + if (params.count("enable_small_channel")) { enable_small_channel = params.at("enable_small_channel").i(); } + if (params.count("fusion_switch_file")) { fusion_switch_file = params.at("fusion_switch_file").s(); } + if (params.count("enable_compress_weight") && params.count("compress_weight_conf")) { + LOG(FATAL) << "enable_compress_weight can not use with compress_weight_conf."; + } + if (params.count("enable_compress_weight")) { enable_compress_weight = params.at("enable_compress_weight").b(); } + if (params.count("compress_weight_conf")) { compress_weight_conf = params.at("compress_weight_conf").s(); } } } @@ -827,6 +883,11 @@ Status NpuAttrs::SetNpuOptimizerAttr(const GraphOptimizationPassOptions &options sess_options["optypelist_for_implmode"] = optypelist_for_implmode; sess_options["input_shape"] = input_shape; sess_options["dynamic_dims"] = dynamic_dims; + sess_options["buffer_optimize"] = buffer_optimize; + sess_options["enable_small_channel"] = std::to_string(enable_small_channel); + sess_options["fusion_switch_file"] = fusion_switch_file; + sess_options["enable_compress_weight"] = std::to_string(enable_compress_weight); + sess_options["compress_weight_conf"] = compress_weight_conf; init_options["precision_mode"] = precision_mode; init_options["profiling_mode"] = std::to_string(profiling_mode); diff --git a/tf_adapter/util/session_manager.cc b/tf_adapter/util/session_manager.cc index b8b98d99faed8a0d1b344f06ad786de9042bb2ab..bca36f120647b3131e3f9a7ceb80bea6dd144304 100644 --- a/tf_adapter/util/session_manager.cc +++ b/tf_adapter/util/session_manager.cc @@ -126,14 +126,6 @@ void SessionManager::PrintGeSessionOptions(std::map &s LOG(INFO) << "[GEOP] optypelist_for_implmode : " << sess_options[ge::OPTYPELIST_FOR_IMPLMODE]; - // reuse memory env - const char *disable_reuse_memory = std::getenv("DISABLE_REUSE_MEMORY"); - if (disable_reuse_memory == nullptr) { - disable_reuse_memory = "0"; - LOG(WARNING) << "[GEOP] can not get DISABLE_REUSE_MEMORY in env, set to default 0"; - } - sess_options["ge.exec.disableReuseMemory"] = disable_reuse_memory; - // dump configuration string dump_step = sess_options[ge::OPTION_EXEC_DUMP_STEP]; LOG(INFO) << "[GEOP] enable_dump :" << sess_options[ge::OPTION_EXEC_ENABLE_DUMP] @@ -146,6 +138,16 @@ void SessionManager::PrintGeSessionOptions(std::map &s // dynamic input config LOG(INFO) << "[GEOP] input_shape :" << sess_options["ge.inputShape"] << ", dynamic_dims :" << sess_options["ge.dynamicDims"]; + + LOG(INFO) << "[GEOP] buffer_optimize :" << sess_options["ge.bufferOptimize"]; + + LOG(INFO) << "[GEOP] enable_small_channel :" << sess_options["ge.enableSmallChannel"]; + + LOG(INFO) << "[GEOP] fusion_switch_file :" << sess_options["ge.fusionSwitchFile"]; + + LOG(INFO) << "[GEOP] enable_compress_weight :" << sess_options["ge.enableCompressWeight"]; + + LOG(INFO) << "[GEOP] compress_weight_conf :" << sess_options["compress_weight_conf"]; } bool SessionManager::CacheGeGraphs(ge::Session *ge_session, ge::Graph &ge_graph) { diff --git a/tfplugin-config.cmake.in b/tfplugin-config.cmake.in new file mode 100644 index 0000000000000000000000000000000000000000..7ecef0a745e11feca003b069b07d8db55a441ab9 --- /dev/null +++ b/tfplugin-config.cmake.in @@ -0,0 +1,8 @@ +@PACKAGE_INIT@ + +set_and_check(TFPLUGIN_BASE_DIR "@PACKAGE_INSTALL_BASE_DIR@") +set_and_check(TFPLUGIN_INCLUDE_DIR "@PACKAGE_INSTALL_INCLUDE_DIR@") +set_and_check(TFPLUGIN_LIBRARY_DIR "@PACKAGE_INSTALL_LIBRARY_DIR@") +set_and_check(TFPLUGIN_CONFIG_DIR "@PACKAGE_INSTALL_CONFIG_DIR@") + +include(${CMAKE_CURRENT_LIST_DIR}/tfplugin-targets.cmake) diff --git a/workspace.bzl.tpl b/workspace.bzl.tpl new file mode 100644 index 0000000000000000000000000000000000000000..505a097ad250540d87c5f9ca19d7224b646c9942 --- /dev/null +++ b/workspace.bzl.tpl @@ -0,0 +1,58 @@ +# Build tf_adapter workspace(Calling by tf_adapter) +def extend_base(): + return "../../../../../" + +def tf_adapter_workspace(): + native.new_local_repository( + name = "tf_adapter_cloud_host_libs", + path = extend_base() + "out/cloud/host/obj/lib", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "tf_adapter_mini_host_libs", + path = extend_base() + "out/mini/host/obj/lib", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "tf_adapter_onetrack_host_libs", + path = extend_base() + "out/onetrack/host/obj/lib", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "tf_adapter_extend_hdrs", + path = extend_base() + "inc", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name="installed_tensorflow", + path=extend_base() + "third_party/tensorflow/compile_deps/tf-1.15.0", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name="installed_tensorflow_libs", + path="{TF_INSTALL_LIB_PATH}", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "local_nlohmann_json_lib", + path = extend_base() + "third_party/json/include/", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "sec_lib", + path = extend_base() + "libc_sec/include/", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + ) + + native.new_local_repository( + name = "python_include", + path = "{PYTHON_INCLUDE_PATH}", + build_file = "@tf_adapter//tf_adapter:module.BUILD", + )