From 29c83fd36db2e58399177e430625711dacba5101 Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Wed, 8 Jan 2025 16:08:16 +0000 Subject: [PATCH] Make profiling info optional and update tests This patch turns all of the values returned by urEventGetProfilingInfo to be optional and updates adapters to handle this by returning the appropriate enum when it is not supported. The tests have also been updated, to ensure that returning a counter of "0" or values equal to the previous profiling event is no longer considered a failure. --- include/ur_api.h | 24 ++++--- scripts/core/event.yml | 12 ++-- source/adapters/cuda/event.cpp | 2 + source/adapters/hip/event.cpp | 2 + source/adapters/level_zero/event.cpp | 12 ++++ source/adapters/native_cpu/event.cpp | 1 + source/loader/ur_libapi.cpp | 2 + source/ur_api.cpp | 2 + .../event/urEventGetProfilingInfo.cpp | 71 +++++++++---------- .../testing/include/uur/optional_queries.h | 12 ++++ 10 files changed, 85 insertions(+), 55 deletions(-) diff --git a/include/ur_api.h b/include/ur_api.h index d7621bda32..e7e107756f 100644 --- a/include/ur_api.h +++ b/include/ur_api.h @@ -7105,21 +7105,21 @@ typedef enum ur_event_info_t { /////////////////////////////////////////////////////////////////////////////// /// @brief Profiling query information type typedef enum ur_profiling_info_t { - /// [uint64_t] A 64-bit value of current device counter in nanoseconds - /// when the event is enqueued + /// [uint64_t][optional-query] A 64-bit value of current device counter in + /// nanoseconds when the event is enqueued UR_PROFILING_INFO_COMMAND_QUEUED = 0, - /// [uint64_t] A 64-bit value of current device counter in nanoseconds - /// when the event is submitted + /// [uint64_t][optional-query] A 64-bit value of current device counter in + /// nanoseconds when the event is submitted UR_PROFILING_INFO_COMMAND_SUBMIT = 1, - /// [uint64_t] A 64-bit value of current device counter in nanoseconds - /// when the event starts execution + /// [uint64_t][optional-query] A 64-bit value of current device counter in + /// nanoseconds when the event starts execution UR_PROFILING_INFO_COMMAND_START = 2, - /// [uint64_t] A 64-bit value of current device counter in nanoseconds - /// when the event has finished execution + /// [uint64_t][optional-query] A 64-bit value of current device counter in + /// nanoseconds when the event has finished execution UR_PROFILING_INFO_COMMAND_END = 3, - /// [uint64_t] A 64-bit value of current device counter in nanoseconds - /// when the event and any child events enqueued by this event on the - /// device have finished execution + /// [uint64_t][optional-query] A 64-bit value of current device counter in + /// nanoseconds when the event and any child events enqueued by this event + /// on the device have finished execution UR_PROFILING_INFO_COMMAND_COMPLETE = 4, /// @cond UR_PROFILING_INFO_FORCE_UINT32 = 0x7fffffff @@ -7193,6 +7193,8 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetInfo( /// - ::UR_RESULT_ERROR_INVALID_EVENT /// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES /// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. UR_APIEXPORT ur_result_t UR_APICALL urEventGetProfilingInfo( /// [in] handle of the event object ur_event_handle_t hEvent, diff --git a/scripts/core/event.yml b/scripts/core/event.yml index da2fa457de..1b0eeca23e 100644 --- a/scripts/core/event.yml +++ b/scripts/core/event.yml @@ -121,15 +121,15 @@ name: $x_profiling_info_t typed_etors: True etors: - name: COMMAND_QUEUED - desc: "[uint64_t] A 64-bit value of current device counter in nanoseconds when the event is enqueued" + desc: "[uint64_t][optional-query] A 64-bit value of current device counter in nanoseconds when the event is enqueued" - name: COMMAND_SUBMIT - desc: "[uint64_t] A 64-bit value of current device counter in nanoseconds when the event is submitted" + desc: "[uint64_t][optional-query] A 64-bit value of current device counter in nanoseconds when the event is submitted" - name: COMMAND_START - desc: "[uint64_t] A 64-bit value of current device counter in nanoseconds when the event starts execution" + desc: "[uint64_t][optional-query] A 64-bit value of current device counter in nanoseconds when the event starts execution" - name: COMMAND_END - desc: "[uint64_t] A 64-bit value of current device counter in nanoseconds when the event has finished execution" + desc: "[uint64_t][optional-query] A 64-bit value of current device counter in nanoseconds when the event has finished execution" - name: COMMAND_COMPLETE - desc: "[uint64_t] A 64-bit value of current device counter in nanoseconds when the event and any child events enqueued by this event on the device have finished execution" + desc: "[uint64_t][optional-query] A 64-bit value of current device counter in nanoseconds when the event and any child events enqueued by this event on the device have finished execution" --- #-------------------------------------------------------------------------- type: function desc: "Get event object information" @@ -198,6 +198,8 @@ returns: - $X_RESULT_ERROR_INVALID_EVENT - $X_RESULT_ERROR_OUT_OF_RESOURCES - $X_RESULT_ERROR_OUT_OF_HOST_MEMORY + - $X_RESULT_ERROR_UNSUPPORTED_ENUMERATION: + - "If `propName` is not supported by the adapter." --- #-------------------------------------------------------------------------- type: function desc: "Wait for a list of events to finish." diff --git a/source/adapters/cuda/event.cpp b/source/adapters/cuda/event.cpp index a6c2208e8f..37792bf5b2 100644 --- a/source/adapters/cuda/event.cpp +++ b/source/adapters/cuda/event.cpp @@ -213,6 +213,8 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetProfilingInfo( return ReturnValue(static_cast(hEvent->getStartTime())); case UR_PROFILING_INFO_COMMAND_END: return ReturnValue(static_cast(hEvent->getEndTime())); + case UR_PROFILING_INFO_COMMAND_COMPLETE: + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: break; } diff --git a/source/adapters/hip/event.cpp b/source/adapters/hip/event.cpp index 81c839cf32..d971207a6c 100644 --- a/source/adapters/hip/event.cpp +++ b/source/adapters/hip/event.cpp @@ -234,6 +234,8 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetProfilingInfo( return ReturnValue(static_cast(hEvent->getStartTime())); case UR_PROFILING_INFO_COMMAND_END: return ReturnValue(static_cast(hEvent->getEndTime())); + case UR_PROFILING_INFO_COMMAND_COMPLETE: + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: break; } diff --git a/source/adapters/level_zero/event.cpp b/source/adapters/level_zero/event.cpp index e12352b6b1..cfcd1d316d 100644 --- a/source/adapters/level_zero/event.cpp +++ b/source/adapters/level_zero/event.cpp @@ -609,6 +609,10 @@ ur_result_t urEventGetProfilingInfo( return ReturnValue(ContextEndTime); } + case UR_PROFILING_INFO_COMMAND_COMPLETE: + logger::error("urEventGetProfilingInfo: " + "UR_PROFILING_INFO_COMMAND_COMPLETE not supported"); + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: logger::error("urEventGetProfilingInfo: not supported ParamName"); return UR_RESULT_ERROR_INVALID_VALUE; @@ -672,6 +676,10 @@ ur_result_t urEventGetProfilingInfo( ContextEndTime *= ZeTimerResolution; return ReturnValue(ContextEndTime); } + case UR_PROFILING_INFO_COMMAND_COMPLETE: + logger::error("urEventGetProfilingInfo: " + "UR_PROFILING_INFO_COMMAND_COMPLETE not supported"); + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: logger::error("urEventGetProfilingInfo: not supported ParamName"); return UR_RESULT_ERROR_INVALID_VALUE; @@ -715,6 +723,10 @@ ur_result_t urEventGetProfilingInfo( // enqueue. // return ReturnValue(uint64_t{0}); + case UR_PROFILING_INFO_COMMAND_COMPLETE: + logger::error("urEventGetProfilingInfo: UR_PROFILING_INFO_COMMAND_COMPLETE " + "not supported"); + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: logger::error("urEventGetProfilingInfo: not supported ParamName"); return UR_RESULT_ERROR_INVALID_VALUE; diff --git a/source/adapters/native_cpu/event.cpp b/source/adapters/native_cpu/event.cpp index 37eaf1f6d1..a52bdd44f7 100644 --- a/source/adapters/native_cpu/event.cpp +++ b/source/adapters/native_cpu/event.cpp @@ -52,6 +52,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetProfilingInfo( case UR_PROFILING_INFO_COMMAND_QUEUED: case UR_PROFILING_INFO_COMMAND_SUBMIT: case UR_PROFILING_INFO_COMMAND_COMPLETE: + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; default: break; } diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp index 5761dab3a4..dfab5ffd36 100644 --- a/source/loader/ur_libapi.cpp +++ b/source/loader/ur_libapi.cpp @@ -4733,6 +4733,8 @@ ur_result_t UR_APICALL urEventGetInfo( /// - ::UR_RESULT_ERROR_INVALID_EVENT /// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES /// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. ur_result_t UR_APICALL urEventGetProfilingInfo( /// [in] handle of the event object ur_event_handle_t hEvent, diff --git a/source/ur_api.cpp b/source/ur_api.cpp index 7023161cb1..fce72302ea 100644 --- a/source/ur_api.cpp +++ b/source/ur_api.cpp @@ -4138,6 +4138,8 @@ ur_result_t UR_APICALL urEventGetInfo( /// - ::UR_RESULT_ERROR_INVALID_EVENT /// - ::UR_RESULT_ERROR_OUT_OF_RESOURCES /// - ::UR_RESULT_ERROR_OUT_OF_HOST_MEMORY +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. ur_result_t UR_APICALL urEventGetProfilingInfo( /// [in] handle of the event object ur_event_handle_t hEvent, diff --git a/test/conformance/event/urEventGetProfilingInfo.cpp b/test/conformance/event/urEventGetProfilingInfo.cpp index 16723df5cf..e63b6078de 100644 --- a/test/conformance/event/urEventGetProfilingInfo.cpp +++ b/test/conformance/event/urEventGetProfilingInfo.cpp @@ -11,8 +11,6 @@ using urEventGetProfilingInfoTest = uur::event::urEventTest; UUR_INSTANTIATE_DEVICE_TEST_SUITE(urEventGetProfilingInfoTest); TEST_P(urEventGetProfilingInfoTest, SuccessCommandQueued) { - UUR_KNOWN_FAILURE_ON(uur::LevelZero{}, uur::LevelZeroV2{}, uur::NativeCPU{}); - const ur_profiling_info_t property_name = UR_PROFILING_INFO_COMMAND_QUEUED; size_t property_size = 0; @@ -29,8 +27,6 @@ TEST_P(urEventGetProfilingInfoTest, SuccessCommandQueued) { } TEST_P(urEventGetProfilingInfoTest, SuccessCommandSubmit) { - UUR_KNOWN_FAILURE_ON(uur::LevelZero{}, uur::LevelZeroV2{}, uur::NativeCPU{}); - const ur_profiling_info_t property_name = UR_PROFILING_INFO_COMMAND_SUBMIT; size_t property_size = 0; @@ -79,9 +75,6 @@ TEST_P(urEventGetProfilingInfoTest, SuccessCommandEnd) { } TEST_P(urEventGetProfilingInfoTest, SuccessCommandComplete) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}, uur::LevelZero{}, - uur::NativeCPU{}); - const ur_profiling_info_t property_name = UR_PROFILING_INFO_COMMAND_COMPLETE; size_t property_size = 0; @@ -98,41 +91,41 @@ TEST_P(urEventGetProfilingInfoTest, SuccessCommandComplete) { } TEST_P(urEventGetProfilingInfoTest, Success) { - UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}, uur::LevelZero{}, - uur::LevelZeroV2{}, uur::NativeCPU{}); - - uint8_t size = 8; - - uint64_t queued_value = 0; - ASSERT_SUCCESS(urEventGetProfilingInfo( - event, UR_PROFILING_INFO_COMMAND_QUEUED, size, &queued_value, nullptr)); - ASSERT_NE(queued_value, 0); - - uint64_t submit_value = 0; - ASSERT_SUCCESS(urEventGetProfilingInfo( - event, UR_PROFILING_INFO_COMMAND_SUBMIT, size, &submit_value, nullptr)); - ASSERT_NE(submit_value, 0); - - uint64_t start_value = 0; - ASSERT_SUCCESS(urEventGetProfilingInfo(event, UR_PROFILING_INFO_COMMAND_START, - size, &start_value, nullptr)); - ASSERT_NE(start_value, 0); + // AMD devices may report a "start" time before the "submit" time + UUR_KNOWN_FAILURE_ON(uur::HIP{}); + + // If a and b are supported, asserts that a <= b + auto test_timing = [=](ur_profiling_info_t a, ur_profiling_info_t b) { + std::stringstream trace{"Profiling Info: "}; + trace << a << " <= " << b; + SCOPED_TRACE(trace.str()); + uint64_t a_time; + auto result = + urEventGetProfilingInfo(event, a, sizeof(a_time), &a_time, nullptr); + if (result == UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION) { + return; + } + ASSERT_SUCCESS(result); - uint64_t end_value = 0; - ASSERT_SUCCESS(urEventGetProfilingInfo(event, UR_PROFILING_INFO_COMMAND_END, - size, &end_value, nullptr)); - ASSERT_NE(end_value, 0); + uint64_t b_time; + result = + urEventGetProfilingInfo(event, b, sizeof(b_time), &b_time, nullptr); + if (result == UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION) { + return; + } + ASSERT_SUCCESS(result); - uint64_t complete_value = 0; - ASSERT_SUCCESS(urEventGetProfilingInfo(event, - UR_PROFILING_INFO_COMMAND_COMPLETE, - size, &complete_value, nullptr)); - ASSERT_NE(complete_value, 0); + // Note: This assumes that the counter doesn't overflow + ASSERT_LE(a_time, b_time); + }; - ASSERT_LE(queued_value, submit_value); - ASSERT_LT(submit_value, start_value); - ASSERT_LT(start_value, end_value); - ASSERT_LE(end_value, complete_value); + test_timing(UR_PROFILING_INFO_COMMAND_QUEUED, + UR_PROFILING_INFO_COMMAND_SUBMIT); + test_timing(UR_PROFILING_INFO_COMMAND_SUBMIT, + UR_PROFILING_INFO_COMMAND_START); + test_timing(UR_PROFILING_INFO_COMMAND_START, UR_PROFILING_INFO_COMMAND_END); + test_timing(UR_PROFILING_INFO_COMMAND_END, + UR_PROFILING_INFO_COMMAND_COMPLETE); } TEST_P(urEventGetProfilingInfoTest, InvalidNullHandle) { diff --git a/test/conformance/testing/include/uur/optional_queries.h b/test/conformance/testing/include/uur/optional_queries.h index d3f670545a..e0a78c18f5 100644 --- a/test/conformance/testing/include/uur/optional_queries.h +++ b/test/conformance/testing/include/uur/optional_queries.h @@ -117,4 +117,16 @@ template <> inline bool isQueryOptional(ur_queue_info_t query) { query) != optional_ur_queue_info_t.end(); } +constexpr std::array optional_ur_profiling_info_t = { + UR_PROFILING_INFO_COMMAND_QUEUED, UR_PROFILING_INFO_COMMAND_SUBMIT, + UR_PROFILING_INFO_COMMAND_START, UR_PROFILING_INFO_COMMAND_END, + UR_PROFILING_INFO_COMMAND_COMPLETE, +}; + +template <> inline bool isQueryOptional(ur_profiling_info_t query) { + return std::find(optional_ur_profiling_info_t.begin(), + optional_ur_profiling_info_t.end(), + query) != optional_ur_profiling_info_t.end(); +} + } // namespace uur