diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 6894bfd9fb..cbf9fe232d 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -1029,6 +1029,11 @@ struct OrtApi { */ ORT_API2_STATUS(SetLanguageProjection, _In_ const OrtEnv* ort_env, _In_ OrtLanguageProjection projection); + /** + * \param out is set to the nanoseconds of profiling's start time + */ + ORT_API2_STATUS(SessionGetProfilingStartTimeNs, _In_ const OrtSession* sess, _Outptr_ uint64_t* out); + }; /* diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 629bd6e78c..ff2ca58696 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -285,6 +285,7 @@ struct Session : Base { char* GetOutputName(size_t index, OrtAllocator* allocator) const; char* GetOverridableInitializerName(size_t index, OrtAllocator* allocator) const; char* EndProfiling(OrtAllocator* allocator) const; + uint64_t GetProfilingStartTimeNs() const; ModelMetadata GetModelMetadata() const; TypeInfo GetInputTypeInfo(size_t index) const; diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index d8c2c28cbd..ffe927d457 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -521,6 +521,12 @@ inline char* Session::EndProfiling(OrtAllocator* allocator) const { return out; } +inline uint64_t Session::GetProfilingStartTimeNs() const { + uint64_t out; + ThrowOnError(GetApi().SessionGetProfilingStartTimeNs(p_, &out)); + return out; +} + inline ModelMetadata Session::GetModelMetadata() const { OrtModelMetadata* out; ThrowOnError(GetApi().SessionGetModelMetadata(p_, &out)); diff --git a/onnxruntime/core/common/profiler.h b/onnxruntime/core/common/profiler.h index a46d3201aa..71f7ce487f 100644 --- a/onnxruntime/core/common/profiler.h +++ b/onnxruntime/core/common/profiler.h @@ -54,12 +54,18 @@ class Profiler { TimePoint StartTime() const; /* - Whether data collection and output from this profiler is enabled. - */ + Whether data collection and output from this profiler is enabled. + */ bool IsEnabled() const { return enabled_; } - + /* + Return the stored start time of profiler + */ + uint64_t GetStartTime() const { + return std::chrono::duration_cast( + profiling_start_time_.time_since_epoch()).count(); + } /* Record a single event. Time is measured till the call of this function from the start_time. diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index c256f60124..ae902322e5 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -1637,6 +1637,10 @@ std::string InferenceSession::EndProfiling() { return std::string(); } +const profiling::Profiler& InferenceSession::GetProfiling() const { + return session_profiler_; +} + AllocatorPtr InferenceSession::GetAllocator(const OrtMemoryInfo& mem_info) const { return session_state_->GetAllocator(mem_info); } diff --git a/onnxruntime/core/session/inference_session.h b/onnxruntime/core/session/inference_session.h index 8fbb621885..1fa732aaf2 100644 --- a/onnxruntime/core/session/inference_session.h +++ b/onnxruntime/core/session/inference_session.h @@ -372,6 +372,11 @@ class InferenceSession { @return the name of the profile file. */ std::string EndProfiling(); + /** + * Return the profiler to access its attributes + @return the profiler object + */ + const profiling::Profiler& GetProfiling() const; /** * Search registered execution providers for an allocator that has characteristics diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index eb939c1937..424873ac5e 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -1762,6 +1762,15 @@ ORT_API_STATUS_IMPL(OrtApis::SetLanguageProjection, _In_ const OrtEnv* ort_env, API_IMPL_END } +ORT_API_STATUS_IMPL(OrtApis::SessionGetProfilingStartTimeNs, _In_ const OrtSession* sess, _Outptr_ uint64_t* out) { + API_IMPL_BEGIN + const auto* session = reinterpret_cast(sess); + auto profiling_start_time = session->GetProfiling().GetStartTime(); + *out = static_cast(profiling_start_time); + return nullptr; + API_IMPL_END +} + // End support for non-tensor types static constexpr OrtApiBase ort_api_base = { @@ -1983,6 +1992,7 @@ static constexpr OrtApi ort_api_1_to_5 = { &OrtApis::TensorAt, &OrtApis::CreateAndRegisterAllocator, &OrtApis::SetLanguageProjection, + &OrtApis::SessionGetProfilingStartTimeNs, }; // Assert to do a limited check to ensure Version 1 of OrtApi never changes (will detect an addition or deletion but not if they cancel out each other) diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index 29e666f15c..21b4aca34d 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -233,4 +233,5 @@ ORT_API_STATUS_IMPL(TensorAt, _Inout_ OrtValue* value, size_t* location_values, ORT_API_STATUS_IMPL(CreateAndRegisterAllocator, _Inout_ OrtEnv* env, _In_ const OrtMemoryInfo* mem_info, _In_ const OrtArenaCfg* arena_cfg); ORT_API_STATUS_IMPL(SetLanguageProjection, _In_ const OrtEnv* ort_env, _In_ OrtLanguageProjection projection); +ORT_API_STATUS_IMPL(SessionGetProfilingStartTimeNs, _In_ const OrtSession* sess, _Outptr_ uint64_t* out); } // namespace OrtApis diff --git a/onnxruntime/test/framework/inference_session_test.cc b/onnxruntime/test/framework/inference_session_test.cc index 46c14a62ec..d0d696f8a3 100644 --- a/onnxruntime/test/framework/inference_session_test.cc +++ b/onnxruntime/test/framework/inference_session_test.cc @@ -668,6 +668,29 @@ TEST(InferenceSessionTests, CheckRunProfilerWithStartProfile) { } } +TEST(InferenceSessionTests, CheckRunProfilerStartTime) { + // Test whether the InferenceSession can access the profiler's start time + SessionOptions so; + + so.session_logid = "CheckRunProfiler"; + so.enable_profiling = true; + so.profile_file_prefix = ORT_TSTR("onnxprofile_profile_test"); + + InferenceSession session_object(so, GetEnvironment()); + ASSERT_STATUS_OK(session_object.Load(MODEL_URI)); + ASSERT_STATUS_OK(session_object.Initialize()); + + uint64_t before_start_time = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count(); // get current time + session_object.StartProfiling("onnxruntime_profile_start"); + uint64_t profiling_start_time = session_object.GetProfiling().GetStartTime(); + uint64_t after_start_time = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + + // the profiler's start time needs to be between before_time and after_time + ASSERT_TRUE(before_start_time <= profiling_start_time && profiling_start_time <= after_start_time); +} + TEST(InferenceSessionTests, MultipleSessionsNoTimeout) { SessionOptions session_options; diff --git a/onnxruntime/test/shared_lib/test_inference.cc b/onnxruntime/test/shared_lib/test_inference.cc index be155eebf5..2cae2269d3 100644 --- a/onnxruntime/test/shared_lib/test_inference.cc +++ b/onnxruntime/test/shared_lib/test_inference.cc @@ -770,6 +770,27 @@ TEST(CApiTest, end_profiling) { ASSERT_TRUE(std::string(profile_file) == std::string()); } +TEST(CApiTest, get_profiling_start_time) { + // Test whether the C_API can access the profiler's start time + Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault); + Ort::SessionOptions session_options; +#ifdef _WIN32 + session_options.EnableProfiling(L"profile_prefix"); +#else + session_options.EnableProfiling("profile_prefix"); +#endif + + uint64_t before_start_time = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count(); // get current time + Ort::Session session_1(*ort_env, MODEL_WITH_CUSTOM_MODEL_METADATA, session_options); + uint64_t profiling_start_time = session_1.GetProfilingStartTimeNs(); + uint64_t after_start_time = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + + // the profiler's start time needs to be between before_time and after_time + ASSERT_TRUE(before_start_time <= profiling_start_time && profiling_start_time <= after_start_time); +} + TEST(CApiTest, model_metadata) { auto allocator = onnxruntime::make_unique(); // The following all tap into the c++ APIs which internally wrap over C APIs