From 41dcf0d32e0e4cc9da7a3840c56c0a096c277d94 Mon Sep 17 00:00:00 2001 From: Yuhong Guo Date: Sat, 29 Apr 2023 12:57:31 +0800 Subject: [PATCH] Expose build information in dynamic lib (#15643) ### Description 1. Add Build Info API to onnx. 2. Fix compile error while building onnxruntime_benchmark in MacOs. ### Motivation and Context 1. When Onnxruntime lib is serving online, we need a way to detect how this lib is built. This PR helps the developer to get the build information using `strings` such as git branch, git commit id, build type and cmake cxx flags, which is showed as follows. ![image](https://user-images.githubusercontent.com/19584326/233794371-b2f95a2c-27fb-4709-a6dd-bf4bb12b0b5b.png) ![image](https://user-images.githubusercontent.com/19584326/233794360-f96f5d2e-332c-405c-83f1-370ccc2b86f8.png) If the build env has no git, there will be no git related infor: ![image](https://user-images.githubusercontent.com/19584326/234558596-298c1b01-9a90-41bf-9372-7259a8f8e5be.png) 3. Fix the following compile error while building benchmark in MacOs. ![image](https://user-images.githubusercontent.com/19584326/233793571-c261ac1f-47b2-434d-a293-7e9edc6c8a66.png) --------- Co-authored-by: Yuhong Guo --- cmake/CMakeLists.txt | 13 +++++++++++++ cmake/onnxruntime_config.h.in | 1 + .../onnxruntime/core/session/onnxruntime_c_api.h | 6 +++++- .../onnxruntime/core/session/onnxruntime_cxx_api.h | 9 ++++++++- .../core/session/onnxruntime_cxx_inline.h | 9 +++++++-- java/src/main/native/ai_onnxruntime_OnnxRuntime.c | 7 ++++++- onnxruntime/__init__.py | 1 + onnxruntime/core/session/onnxruntime_c_api.cc | 9 +++++++-- onnxruntime/core/session/ort_apis.h | 3 ++- onnxruntime/python/onnxruntime_pybind_module.cc | 1 + onnxruntime/test/onnx/main.cc | 3 ++- onnxruntime/test/onnx/microbenchmark/activation.cc | 4 ++-- onnxruntime/test/onnx/microbenchmark/batchnorm.cc | 4 ++-- onnxruntime/test/onnx/microbenchmark/common.h | 4 +++- onnxruntime/test/onnx/microbenchmark/eigen.cc | 4 ++-- onnxruntime/test/onnx/microbenchmark/gelu.cc | 3 +-- onnxruntime/test/onnx/microbenchmark/tptest.cc | 4 ++-- onnxruntime/test/python/onnxruntime_test_python.py | 4 ++++ onnxruntime/test/shared_lib/test_inference.cc | 4 ++-- .../orttraining/python/orttraining_python_module.cc | 2 ++ 20 files changed, 73 insertions(+), 22 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 65c6faecd4..a5496e1638 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -1236,6 +1236,19 @@ if (onnxruntime_USE_VITISAI) endif() endif() +set(ORT_BUILD_INFO "ORT Build Info: ") +find_package(Git) +if (Git_FOUND) + execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format=%h + OUTPUT_VARIABLE ORT_GIT_COMMIT) + string(STRIP "${ORT_GIT_COMMIT}" ORT_GIT_COMMIT) + execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD + OUTPUT_VARIABLE ORT_GIT_BRANCH) + string(STRIP "${ORT_GIT_BRANCH}" ORT_GIT_BRANCH) + string(APPEND ORT_BUILD_INFO "git-branch=${ORT_GIT_BRANCH}, git-commit-id=${ORT_GIT_COMMIT}, ") +endif() +string(APPEND ORT_BUILD_INFO "build type=${CMAKE_BUILD_TYPE}") +string(APPEND ORT_BUILD_INFO ", cmake cxx flags: ${CMAKE_CXX_FLAGS}") configure_file(onnxruntime_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_config.h) if (WIN32) configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/Debug/requirements.txt) diff --git a/cmake/onnxruntime_config.h.in b/cmake/onnxruntime_config.h.in index 44d4788acb..9fc46018da 100644 --- a/cmake/onnxruntime_config.h.in +++ b/cmake/onnxruntime_config.h.in @@ -22,3 +22,4 @@ #cmakedefine HAS_BITWISE_INSTEAD_OF_LOGICAL #cmakedefine HAS_REALLOCARRAY #cmakedefine ORT_VERSION "@ORT_VERSION@" +#cmakedefine ORT_BUILD_INFO "@ORT_BUILD_INFO@" diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index d9bbe423dc..73be22527c 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -98,8 +98,11 @@ extern "C" { #ifndef ORT_TSTR #ifdef _WIN32 #define ORT_TSTR(X) L##X +// When X is a macro, L##X is not defined. In this case, we need to use ORT_TSTR_ON_MACRO. +#define ORT_TSTR_ON_MACRO(X) L"" X #else #define ORT_TSTR(X) X +#define ORT_TSTR_ON_MACRO(X) X #endif #endif @@ -626,7 +629,8 @@ struct OrtApiBase { * older than the version created with this header file. */ const OrtApi*(ORT_API_CALL* GetApi)(uint32_t version)NO_EXCEPTION; - const char*(ORT_API_CALL* GetVersionString)(void)NO_EXCEPTION; ///< Returns a null terminated string of the version of the Onnxruntime library (eg: "1.8.1") + const ORTCHAR_T*(ORT_API_CALL* GetVersionString)(void)NO_EXCEPTION; ///< Returns a null terminated string of the version of the Onnxruntime library (eg: "1.8.1") + const ORTCHAR_T*(ORT_API_CALL* GetBuildInfoString)(void)NO_EXCEPTION; ///< Returns a null terminated string of the build info including git info and cxx flags }; typedef struct OrtApiBase OrtApiBase; diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 0c8170b7d6..4407fed1bb 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -125,7 +125,14 @@ inline const OrtApi& GetApi() noexcept { return *Global::api_; } /// This function returns the onnxruntime version string /// /// version string major.minor.rev -std::string GetVersionString(); +std::basic_string GetVersionString(); + +/// +/// This function returns the onnxruntime build information: including git branch, +/// git commit id, build type(Debug/Release/RelWithDebInfo) and cmake cpp flags. +/// +/// string +std::basic_string GetBuildInfoString(); /// /// This is a C++ wrapper for OrtApi::GetAvailableProviders() and diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 25dd033369..c9a1e13866 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -1987,8 +1987,13 @@ inline void CustomOpApi::ReleaseKernelInfo(_Frees_ptr_opt_ OrtKernelInfo* info_c api_.ReleaseKernelInfo(info_copy); } -inline std::string GetVersionString() { - std::string result = OrtGetApiBase()->GetVersionString(); +inline std::basic_string GetVersionString() { + std::basic_string result = OrtGetApiBase()->GetVersionString(); + return result; +} + +inline std::basic_string GetBuildInfoString() { + std::basic_string result = OrtGetApiBase()->GetBuildInfoString(); return result; } diff --git a/java/src/main/native/ai_onnxruntime_OnnxRuntime.c b/java/src/main/native/ai_onnxruntime_OnnxRuntime.c index d0c4be87d9..5165f3499e 100644 --- a/java/src/main/native/ai_onnxruntime_OnnxRuntime.c +++ b/java/src/main/native/ai_onnxruntime_OnnxRuntime.c @@ -76,8 +76,13 @@ JNIEXPORT jobjectArray JNICALL Java_ai_onnxruntime_OnnxRuntime_getAvailableProvi JNIEXPORT jstring JNICALL Java_ai_onnxruntime_OnnxRuntime_initialiseVersion (JNIEnv * jniEnv, jclass clazz) { (void)clazz; // required JNI parameter not needed by functions which don't access their host class. - const char* version = OrtGetApiBase()->GetVersionString(); + const ORTCHAR_T* version = OrtGetApiBase()->GetVersionString(); assert(version != NULL); +#ifdef _WIN32 + jsize len = (jsize)(wcslen(version)); + jstring versionStr = (*jniEnv)->NewString(jniEnv, (const jchar*)version, len); +#else jstring versionStr = (*jniEnv)->NewStringUTF(jniEnv, version); +#endif return versionStr; } diff --git a/onnxruntime/__init__.py b/onnxruntime/__init__.py index d052d9644c..1da5824cf7 100644 --- a/onnxruntime/__init__.py +++ b/onnxruntime/__init__.py @@ -38,6 +38,7 @@ try: from onnxruntime.capi._pybind_state import enable_telemetry_events # noqa: F401 from onnxruntime.capi._pybind_state import get_all_providers # noqa: F401 from onnxruntime.capi._pybind_state import get_available_providers # noqa: F401 + from onnxruntime.capi._pybind_state import get_build_info # noqa: F401 from onnxruntime.capi._pybind_state import get_device # noqa: F401 from onnxruntime.capi._pybind_state import get_version_string # noqa: F401 from onnxruntime.capi._pybind_state import set_default_logger_severity # noqa: F401 diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 2b6c9a4d48..d27bdf05a0 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -2381,6 +2381,7 @@ ORT_API(const OrtTrainingApi*, OrtApis::GetTrainingApi, uint32_t version) { static constexpr OrtApiBase ort_api_base = { &OrtApis::GetApi, &OrtApis::GetVersionString, + &OrtApis::GetBuildInfoString, }; /* Rules on how to add a new Ort API version @@ -2763,8 +2764,12 @@ ORT_API(const OrtApi*, OrtApis::GetApi, uint32_t version) { return nullptr; // Unsupported version } -ORT_API(const char*, OrtApis::GetVersionString) { - return ORT_VERSION; +ORT_API(const ORTCHAR_T*, OrtApis::GetVersionString) { + return ORT_TSTR_ON_MACRO(ORT_VERSION); +} + +ORT_API(const ORTCHAR_T*, OrtApis::GetBuildInfoString) { + return ORT_TSTR_ON_MACRO(ORT_BUILD_INFO); } const OrtApiBase* ORT_API_CALL OrtGetApiBase(void) NO_EXCEPTION { diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index f51e807374..81429a19e4 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -4,7 +4,8 @@ namespace OrtApis { ORT_API(const OrtApi*, GetApi, uint32_t version); -ORT_API(const char*, GetVersionString); +ORT_API(const ORTCHAR_T*, GetVersionString); +ORT_API(const ORTCHAR_T*, GetBuildInfoString); ORT_API(void, ReleaseEnv, OrtEnv*); ORT_API(void, ReleaseStatus, _Frees_ptr_opt_ OrtStatus*); diff --git a/onnxruntime/python/onnxruntime_pybind_module.cc b/onnxruntime/python/onnxruntime_pybind_module.cc index c224bec218..f320707697 100644 --- a/onnxruntime/python/onnxruntime_pybind_module.cc +++ b/onnxruntime/python/onnxruntime_pybind_module.cc @@ -22,6 +22,7 @@ PYBIND11_MODULE(onnxruntime_pybind11_state, m) { "from highest to lowest."); m.def("get_version_string", []() -> std::string { return ORT_VERSION; }); + m.def("get_build_info", []() -> std::string { return ORT_BUILD_INFO; }); } } // namespace python } // namespace onnxruntime diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index 469d7c0e37..3ee2f4ddcf 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -29,6 +29,7 @@ using namespace onnxruntime; namespace { void usage() { + auto version_string = ToUTF8String(OrtGetApiBase()->GetVersionString()); printf( "onnx_test_runner [options...] \n" "Options:\n" @@ -64,7 +65,7 @@ void usage() { "\t-h: help\n" "\n" "onnxruntime version: %s\n", - OrtGetApiBase()->GetVersionString()); + version_string.c_str()); } static TestTolerances LoadTestTolerances(bool enable_cuda, bool enable_openvino, bool useCustom, double atol, double rtol) { diff --git a/onnxruntime/test/onnx/microbenchmark/activation.cc b/onnxruntime/test/onnx/microbenchmark/activation.cc index 63a595b17a..b5bf420f39 100644 --- a/onnxruntime/test/onnx/microbenchmark/activation.cc +++ b/onnxruntime/test/onnx/microbenchmark/activation.cc @@ -97,7 +97,7 @@ class MyIExecutionFrame : public IExecutionFrame { Status CreateNodeOutputMLValueImpl(OrtValue& /*ort_value*/, int /*ort_value_idx*/, const TensorShape* /*shape*/) override { abort(); } - AllocatorPtr GetAllocatorImpl(const OrtMemoryInfo& info) const { + AllocatorPtr GetAllocatorImpl(const OrtMemoryInfo& info) const override { return a_.GetAllocator(info.mem_type); } @@ -126,7 +126,7 @@ class MyIExecutionFrame : public IExecutionFrame { return Status::OK(); } - Status CopyTensor(const Tensor& /*src*/, Tensor& /*dest*/) const { + Status CopyTensor(const Tensor& /*src*/, Tensor& /*dest*/) const override { return Status::OK(); } }; diff --git a/onnxruntime/test/onnx/microbenchmark/batchnorm.cc b/onnxruntime/test/onnx/microbenchmark/batchnorm.cc index 516664147d..eb435618cd 100644 --- a/onnxruntime/test/onnx/microbenchmark/batchnorm.cc +++ b/onnxruntime/test/onnx/microbenchmark/batchnorm.cc @@ -2,14 +2,14 @@ #include "core/util/thread_utils.h" #include -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif #include "core/common/eigen_common_wrapper.h" -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif diff --git a/onnxruntime/test/onnx/microbenchmark/common.h b/onnxruntime/test/onnx/microbenchmark/common.h index 5850102258..89ae8ded70 100644 --- a/onnxruntime/test/onnx/microbenchmark/common.h +++ b/onnxruntime/test/onnx/microbenchmark/common.h @@ -2,7 +2,9 @@ #include #include +#ifdef _WIN32 #include +#endif #include #include @@ -46,4 +48,4 @@ T* GenerateArrayWithRandomValue(size_t batch_size, T low, T high) { data[i] = static_cast(dist(gen)); } return data; -} \ No newline at end of file +} diff --git a/onnxruntime/test/onnx/microbenchmark/eigen.cc b/onnxruntime/test/onnx/microbenchmark/eigen.cc index b3b2c55600..29894316ed 100644 --- a/onnxruntime/test/onnx/microbenchmark/eigen.cc +++ b/onnxruntime/test/onnx/microbenchmark/eigen.cc @@ -1,4 +1,4 @@ -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #if __GNUC__ >= 6 #pragma GCC diagnostic ignored "-Wignored-attributes" @@ -25,7 +25,7 @@ #include #include #include -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #elif defined(_MSC_VER) #pragma warning(pop) diff --git a/onnxruntime/test/onnx/microbenchmark/gelu.cc b/onnxruntime/test/onnx/microbenchmark/gelu.cc index 73127f6dec..3a3669b5d6 100644 --- a/onnxruntime/test/onnx/microbenchmark/gelu.cc +++ b/onnxruntime/test/onnx/microbenchmark/gelu.cc @@ -137,10 +137,9 @@ static void BM_ScaledTanhParallelFor(benchmark::State& state) { std::unique_ptr tp( concurrency::CreateThreadPool(&onnxruntime::Env::Default(), tpo, concurrency::ThreadPoolType::INTRA_OP)); const float alpha_ = 0.3f; - const float beta_ = 0.6f; for (auto _ : state) { ThreadPool::TryParallelFor(tp.get(), batch_size, cost, - [alpha_, beta_, data, output](ptrdiff_t first, ptrdiff_t last) { + [alpha_, data, output](ptrdiff_t first, ptrdiff_t last) { ptrdiff_t len = last - first; float* output_ptr = output + first; onnxruntime::ConstEigenVectorArrayMap xm(data + first, len); diff --git a/onnxruntime/test/onnx/microbenchmark/tptest.cc b/onnxruntime/test/onnx/microbenchmark/tptest.cc index b2d745bfbb..e51b124542 100644 --- a/onnxruntime/test/onnx/microbenchmark/tptest.cc +++ b/onnxruntime/test/onnx/microbenchmark/tptest.cc @@ -30,7 +30,7 @@ BENCHMARK(BM_CreateThreadPool) // On Xeon W-2123 CPU, it takes about 2ns for each iteration #ifdef _WIN32 #pragma optimize("", off) -#else +#elif defined(__GNUC__) && !defined(__clang__) #pragma GCC push_options #pragma GCC optimize("O0") #endif @@ -42,7 +42,7 @@ void SimpleForLoop(ptrdiff_t first, ptrdiff_t last) { } #ifdef _WIN32 #pragma optimize("", on) -#else +#elif defined(__GNUC__) && !defined(__clang__) #pragma GCC pop_options #endif diff --git a/onnxruntime/test/python/onnxruntime_test_python.py b/onnxruntime/test/python/onnxruntime_test_python.py index e700b48acd..416cdd5dda 100644 --- a/onnxruntime/test/python/onnxruntime_test_python.py +++ b/onnxruntime/test/python/onnxruntime_test_python.py @@ -69,6 +69,10 @@ class TestInferenceSession(unittest.TestCase): def testGetVersionString(self): # noqa: N802 self.assertIsNot(onnxrt.get_version_string(), None) + def testGetBuildInfo(self): # noqa: N802 + self.assertIsNot(onnxrt.get_build_info(), None) + self.assertIn("Build Info", onnxrt.get_build_info()) + def testModelSerialization(self): # noqa: N802 try: so = onnxrt.SessionOptions() diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index 0b79b29b20..af1df0ed63 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -2208,9 +2208,9 @@ TEST(CApiTest, get_available_providers_cpp) { } TEST(CApiTest, get_version_string_cpp) { - std::string version_string = Ort::GetVersionString(); + std::basic_string version_string = Ort::GetVersionString(); ASSERT_FALSE(version_string.empty()); - ASSERT_EQ(version_string, ORT_VERSION); + ASSERT_EQ(version_string, std::basic_string(ORT_TSTR_ON_MACRO(ORT_VERSION))); } TEST(CApiTest, TestSharedAllocators) { diff --git a/orttraining/orttraining/python/orttraining_python_module.cc b/orttraining/orttraining/python/orttraining_python_module.cc index c378733e7e..aee2b8b0b7 100644 --- a/orttraining/orttraining/python/orttraining_python_module.cc +++ b/orttraining/orttraining/python/orttraining_python_module.cc @@ -360,6 +360,8 @@ PYBIND11_MODULE(onnxruntime_pybind11_state, m) { m.def("get_version_string", []() -> std::string { return ORT_VERSION; }); + m.def("get_build_info", []() -> std::string { return ORT_BUILD_INFO; }); + m.def( "clear_training_ep_instances", []() -> void { GetTrainingEnv().ClearExecutionProviderInstances();