diff --git a/samples/api_buffered_tracing/client.cpp b/samples/api_buffered_tracing/client.cpp index 0bef606f76..00d9e7c3c9 100644 --- a/samples/api_buffered_tracing/client.cpp +++ b/samples/api_buffered_tracing/client.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,16 @@ struct source_location std::string context = {}; }; -using call_stack_t = std::vector; +using call_stack_t = std::vector; +using buffer_kind_names_t = std::map; +using buffer_kind_operation_names_t = + std::map>; + +struct buffer_name_info +{ + buffer_kind_names_t kind_names = {}; + buffer_kind_operation_names_t operation_names = {}; +}; rocprofiler_client_id_t* client_id = nullptr; rocprofiler_client_finalize_t client_fini_func = nullptr; @@ -129,48 +139,53 @@ print_call_stack(const call_stack_t& _call_stack) if(cleanup) cleanup(ofs); } -void -store_buffer_id_names(call_stack_t* tool_data) +buffer_name_info +get_buffer_tracing_names() { + auto cb_name_info = buffer_name_info{}; // - // buffered for each kind operation + // callback for each kind operation // - static auto tracing_operation_names_cb = [](rocprofiler_service_buffer_tracing_kind_t /*kindv*/, - uint32_t /*operation*/, - const char* operation_name, - void* data_v) { - static_cast(data_v)->emplace_back( - source_location{"rocprofiler_iterate_buffer_trace_kind_operation_names", - __FILE__, - __LINE__, - std::string{" "} + std::string{operation_name}}); - return 0; - }; + static auto tracing_kind_operation_cb = + [](rocprofiler_service_buffer_tracing_kind_t kindv, uint32_t operation, void* data_v) { + auto* name_info_v = static_cast(data_v); + + if(kindv == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) + { + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_buffer_tracing_kind_operation_name( + kindv, operation, &name, nullptr), + "query buffer tracing kind operation name"); + if(name) name_info_v->operation_names[kindv][operation] = name; + } + return 0; + }; // // callback for each buffer kind (i.e. domain) // - static auto tracing_kind_names_cb = - [](rocprofiler_service_buffer_tracing_kind_t kind, const char* kind_name, void* data) { - // store the buffer kind name - static_cast(data)->emplace_back( - source_location{"rocprofiler_iterate_buffer_trace_kind_names ", - __FILE__, - __LINE__, - kind_name}); + static auto tracing_kind_cb = [](rocprofiler_service_buffer_tracing_kind_t kind, void* data) { + // store the buffer kind name + auto* name_info_v = static_cast(data); + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_buffer_tracing_kind_name(kind, &name, nullptr), + "query buffer tracing kind operation name"); + if(name) name_info_v->kind_names[kind] = name; - // store the operation names for the HSA API - if(kind == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) - { - rocprofiler_iterate_buffer_tracing_kind_operation_names( - kind, tracing_operation_names_cb, data); - } + if(kind == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) + { + ROCPROFILER_CALL(rocprofiler_iterate_buffer_tracing_kind_operations( + kind, tracing_kind_operation_cb, static_cast(data)), + "iterating buffer tracing kind operations"); + } + return 0; + }; - return 0; - }; + ROCPROFILER_CALL(rocprofiler_iterate_buffer_tracing_kinds(tracing_kind_cb, + static_cast(&cb_name_info)), + "iterating buffer tracing kinds"); - rocprofiler_iterate_buffer_tracing_kind_names(tracing_kind_names_cb, - static_cast(tool_data)); + return cb_name_info; } void @@ -256,10 +271,33 @@ tool_init(rocprofiler_client_finalize_t fini_func, void* tool_data) { assert(tool_data != nullptr); - static_cast(tool_data)->emplace_back( - source_location{__FUNCTION__, __FILE__, __LINE__, ""}); + auto* call_stack_v = static_cast(tool_data); - store_buffer_id_names(static_cast(tool_data)); + call_stack_v->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, ""}); + + buffer_name_info name_info = get_buffer_tracing_names(); + + for(const auto& itr : name_info.operation_names) + { + auto name_idx = std::stringstream{}; + name_idx << " [" << std::setw(3) << static_cast(itr.first) << "]"; + call_stack_v->emplace_back( + source_location{"rocprofiler_buffer_tracing_kind_names " + name_idx.str(), + __FILE__, + __LINE__, + name_info.kind_names.at(itr.first)}); + + for(const auto& ditr : itr.second) + { + auto operation_idx = std::stringstream{}; + operation_idx << " [" << std::setw(3) << static_cast(ditr.first) << "]"; + call_stack_v->emplace_back(source_location{ + "rocprofiler_buffer_tracing_kind_operation_names" + operation_idx.str(), + __FILE__, + __LINE__, + std::string{"- "} + std::string{ditr.second}}); + } + } client_fini_func = fini_func; diff --git a/samples/api_callback_tracing/client.cpp b/samples/api_callback_tracing/client.cpp index 33fa74820f..f1b5823b9c 100644 --- a/samples/api_callback_tracing/client.cpp +++ b/samples/api_callback_tracing/client.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -72,7 +75,16 @@ struct source_location std::string context = {}; }; -using call_stack_t = std::vector; +using call_stack_t = std::vector; +using callback_kind_names_t = std::map; +using callback_kind_operation_names_t = + std::map>; + +struct callback_name_info +{ + callback_kind_names_t kind_names = {}; + callback_kind_operation_names_t operation_names = {}; +}; rocprofiler_client_id_t* client_id = nullptr; rocprofiler_client_finalize_t client_fini_func = nullptr; @@ -109,11 +121,12 @@ print_call_stack(const call_stack_t& _call_stack) std::cout << "Outputting collected data to " << ofname << "...\n" << std::flush; size_t n = 0; + *ofs << std::left; for(const auto& itr : _call_stack) { *ofs << std::setw(2) << ++n << "/" << std::setw(2) << _call_stack.size() << " "; *ofs << "[" << fs::path{itr.file}.filename() << ":" << itr.line << "] " << std::setw(20) - << std::left << itr.function; + << itr.function; if(!itr.context.empty()) *ofs << " :: " << itr.context; *ofs << "\n"; } @@ -123,60 +136,74 @@ print_call_stack(const call_stack_t& _call_stack) if(cleanup) cleanup(ofs); } -void -store_callback_id_names(call_stack_t* tool_data) +callback_name_info +get_callback_id_names() { + auto cb_name_info = callback_name_info{}; // // callback for each kind operation // - static auto tracing_operation_names_cb = - [](rocprofiler_service_callback_tracing_kind_t /*kindv*/, - uint32_t /*operation*/, - const char* operation_name, - void* data_v) { - static_cast(data_v)->emplace_back( - source_location{"rocprofiler_iterate_callback_tracing_kind_operation_names", - __FILE__, - __LINE__, - std::string{" "} + std::string{operation_name}}); + static auto tracing_kind_operation_cb = + [](rocprofiler_service_callback_tracing_kind_t kindv, uint32_t operation, void* data_v) { + auto* name_info_v = static_cast(data_v); + + if(kindv == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) + { + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_callback_tracing_kind_operation_name( + kindv, operation, &name, nullptr), + "query callback tracing kind operation name"); + if(name) name_info_v->operation_names[kindv][operation] = name; + } return 0; }; // // callback for each callback kind (i.e. domain) // - static auto tracing_kind_names_cb = [](rocprofiler_service_callback_tracing_kind_t kind, - const char* kind_name, - void* data) { + static auto tracing_kind_cb = [](rocprofiler_service_callback_tracing_kind_t kind, void* data) { // store the callback kind name - static_cast(data)->emplace_back(source_location{ - "rocprofiler_iterate_callback_tracing_kind_names ", __FILE__, __LINE__, kind_name}); + auto* name_info_v = static_cast(data); + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_callback_tracing_kind_name(kind, &name, nullptr), + "query callback tracing kind operation name"); + if(name) name_info_v->kind_names[kind] = name; - // store the operation names for the HSA API if(kind == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) { - rocprofiler_iterate_callback_tracing_kind_operation_names( - kind, tracing_operation_names_cb, data); + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kind_operations( + kind, tracing_kind_operation_cb, static_cast(data)), + "iterating callback tracing kind operations"); } - return 0; }; - rocprofiler_iterate_callback_tracing_kind_names(tracing_kind_names_cb, - static_cast(tool_data)); + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kinds(tracing_kind_cb, + static_cast(&cb_name_info)), + "iterating callback tracing kinds"); + + return cb_name_info; } void tool_tracing_callback(rocprofiler_callback_tracing_record_t record, - rocprofiler_user_data_t*, - void* user_data) + rocprofiler_user_data_t* user_data, + void* callback_data) { - assert(user_data != nullptr); + assert(callback_data != nullptr); + + auto now = std::chrono::steady_clock::now().time_since_epoch().count(); + uint64_t dt = 0; + if(record.phase == ROCPROFILER_SERVICE_CALLBACK_PHASE_ENTER) + user_data->value = now; + else + dt = (now - user_data->value); auto info = std::stringstream{}; - info << "tid=" << record.thread_id << ", cid=" << record.correlation_id.internal - << ", kind=" << record.kind << ", operation=" << record.operation - << ", phase=" << record.phase; + info << std::left << "tid=" << record.thread_id << ", cid=" << std::setw(3) + << record.correlation_id.internal << ", kind=" << record.kind + << ", operation=" << std::setw(3) << record.operation << ", phase=" << record.phase + << ", dt_nsec=" << std::setw(6) << dt; auto info_data_cb = [](rocprofiler_service_callback_tracing_kind_t, uint32_t, @@ -193,7 +220,7 @@ tool_tracing_callback(rocprofiler_callback_tracing_record_t record, }; auto info_data = std::stringstream{}; - ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_operation_args( + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kind_operation_args( record, info_data_cb, static_cast(&info_data)), "Failure iterating trace operation args"); @@ -202,8 +229,8 @@ tool_tracing_callback(rocprofiler_callback_tracing_record_t record, static auto _mutex = std::mutex{}; _mutex.lock(); - static_cast(user_data)->emplace_back( - source_location{__FUNCTION__, __FILE__, __LINE__, info.str()}); + static_cast(callback_data) + ->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, info.str()}); _mutex.unlock(); } @@ -212,10 +239,33 @@ tool_init(rocprofiler_client_finalize_t fini_func, void* tool_data) { assert(tool_data != nullptr); - static_cast(tool_data)->emplace_back( - source_location{__FUNCTION__, __FILE__, __LINE__, ""}); + auto* call_stack_v = static_cast(tool_data); - store_callback_id_names(static_cast(tool_data)); + call_stack_v->emplace_back(source_location{__FUNCTION__, __FILE__, __LINE__, ""}); + + callback_name_info name_info = get_callback_id_names(); + + for(const auto& itr : name_info.operation_names) + { + auto name_idx = std::stringstream{}; + name_idx << " [" << std::setw(3) << static_cast(itr.first) << "]"; + call_stack_v->emplace_back( + source_location{"rocprofiler_callback_tracing_kind_names " + name_idx.str(), + __FILE__, + __LINE__, + name_info.kind_names.at(itr.first)}); + + for(const auto& ditr : itr.second) + { + auto operation_idx = std::stringstream{}; + operation_idx << " [" << std::setw(3) << static_cast(ditr.first) << "]"; + call_stack_v->emplace_back(source_location{ + "rocprofiler_callback_tracing_kind_operation_names" + operation_idx.str(), + __FILE__, + __LINE__, + std::string{"- "} + std::string{ditr.second}}); + } + } client_fini_func = fini_func; diff --git a/source/include/rocprofiler/buffer_tracing.h b/source/include/rocprofiler/buffer_tracing.h index 0e3fbb000d..a6e7c4460d 100644 --- a/source/include/rocprofiler/buffer_tracing.h +++ b/source/include/rocprofiler/buffer_tracing.h @@ -206,20 +206,17 @@ typedef struct * @brief Callback function for mapping @ref rocprofiler_service_buffer_tracing_kind_t ids to * string names. @see rocprofiler_iterate_buffer_trace_kind_names. */ -typedef int (*rocprofiler_buffer_tracing_kind_name_cb_t)( - rocprofiler_service_buffer_tracing_kind_t kind, - const char* kind_name, - void* data); +typedef int (*rocprofiler_buffer_tracing_kind_cb_t)(rocprofiler_service_buffer_tracing_kind_t kind, + void* data); /** * @brief Callback function for mapping the operations of a given @ref * rocprofiler_service_buffer_tracing_kind_t to string names. @see * rocprofiler_iterate_buffer_trace_kind_operation_names. */ -typedef int (*rocprofiler_buffer_tracing_operation_name_cb_t)( +typedef int (*rocprofiler_buffer_tracing_kind_operation_cb_t)( rocprofiler_service_buffer_tracing_kind_t kind, uint32_t operation, - const char* operation_name, void* data); /** @@ -241,7 +238,52 @@ rocprofiler_configure_buffer_tracing_service(rocprofiler_context_id_t rocprofiler_buffer_id_t buffer_id); /** - * @brief Iterate over all the mappings of the callback tracing kinds and get a callback with the id + * @brief Query the name of the buffer tracing kind. The name retrieved from this function is a + * string literal that is encoded in the read-only section of the binary (i.e. it is always + * "allocated" and never "deallocated"). + * + * @param kind [in] Buffer tracing domain + * @param name [out] If non-null and the name is a constant string that does not require dynamic + * allocation, this paramter will be set to the address of the string literal, otherwise it will + * be set to nullptr + * @param name_len [out] If non-null, this will be assigned the length of the name (regardless of + * the name is a constant string or requires dynamic allocation) + * @return rocprofiler_status_t Returns @ref ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND if the + * domain id is not valid. Returns @ref ROCPROFILER_STATUS_SUCCESS for a valid domain regardless if + * there is a constant string or not. + */ +rocprofiler_status_t +rocprofiler_query_buffer_tracing_kind_name(rocprofiler_service_buffer_tracing_kind_t kind, + const char** name, + uint64_t* name_len) ROCPROFILER_API; + +/** + * @brief Query the name of the buffer tracing kind. The name retrieved from this function is a + * string literal that is encoded in the read-only section of the binary (i.e. it is always + * "allocated" and never "deallocated"). + * + * @param kind [in] Buffer tracing domain + * @param operation [in] Enumeration id value which maps to a specific API function or event type + * @param name [out] If non-null and the name is a constant string that does not require dynamic + * allocation, this paramter will be set to the address of the string literal, otherwise it will + * be set to nullptr + * @param name_len [out] If non-null, this will be assigned the length of the name (regardless of + * the name is a constant string or requires dynamic allocation) + * @return rocprofiler_status_t Returns @ref ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND on an invalid + * domain id. Returns @ref ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND if the operation number is + * not recognized for the given domain. Returns @ref ROCPROFILER_STATUS_ERROR_NOT_IMPLEMENTED if + * rocprofiler does not support providing the operation name within this domain. Returns @ref + * ROCPROFILER_STATUS_SUCCESS for valid domain and operation regardless of whether there is a + * constant string or not. + */ +rocprofiler_status_t +rocprofiler_query_buffer_tracing_kind_operation_name(rocprofiler_service_buffer_tracing_kind_t kind, + uint32_t operation, + const char** name, + uint64_t* name_len) ROCPROFILER_API; + +/** + * @brief Iterate over all the mappings of the buffer tracing kinds and get a buffer with the id * mapped to a constant string. The strings provided in the arg will be valid pointers for the * entire duration of the program. It is recommended to call this function once and cache this data * in the client instead of making multiple on-demand calls. @@ -251,15 +293,14 @@ rocprofiler_configure_buffer_tracing_service(rocprofiler_context_id_t * @param [in] data User data passed back into the callback */ rocprofiler_status_t ROCPROFILER_API -rocprofiler_iterate_buffer_tracing_kind_names(rocprofiler_buffer_tracing_kind_name_cb_t callback, - void* data) ROCPROFILER_NONNULL(1); +rocprofiler_iterate_buffer_tracing_kinds(rocprofiler_buffer_tracing_kind_cb_t callback, void* data) + ROCPROFILER_NONNULL(1); /** - * @brief Iterates over all the mappings of the operations for a given @ref - * rocprofiler_service_buffer_tracing_kind_t and invokes the callback with the kind, operation id, - * and the string mapping to the operation id. The strings provided in the callback arg will be - * valid pointers for the entire duration of the program. It is recommended to call this function - * once per kind, and cache this data in the client instead of making multiple on-demand calls. + * @brief Iterates over all the operations for a given @ref + * rocprofiler_service_buffer_tracing_kind_t and invokes the callback with the kind and operation + * id. This is useful to build a map of the operation names during tool initialization instead of + * querying rocprofiler everytime in the callback hotpath. * * @param [in] kind which buffer tracing kind operations to iterate over * @param [in] callback Callback function invoked for each operation associated with @ref @@ -267,9 +308,9 @@ rocprofiler_iterate_buffer_tracing_kind_names(rocprofiler_buffer_tracing_kind_na * @param [in] data User data passed back into the callback */ rocprofiler_status_t ROCPROFILER_API -rocprofiler_iterate_buffer_tracing_kind_operation_names( +rocprofiler_iterate_buffer_tracing_kind_operations( rocprofiler_service_buffer_tracing_kind_t kind, - rocprofiler_buffer_tracing_operation_name_cb_t callback, + rocprofiler_buffer_tracing_kind_operation_cb_t callback, void* data) ROCPROFILER_NONNULL(2); /** @} */ diff --git a/source/include/rocprofiler/callback_tracing.h b/source/include/rocprofiler/callback_tracing.h index 98bc570d3c..d526c68c29 100644 --- a/source/include/rocprofiler/callback_tracing.h +++ b/source/include/rocprofiler/callback_tracing.h @@ -157,9 +157,8 @@ typedef void (*rocprofiler_callback_tracing_cb_t)(rocprofiler_callback_tracing_r * @brief Callback function for mapping @ref rocprofiler_service_callback_tracing_kind_t ids to * string names. @see rocprofiler_iterate_callback_tracing_kind_names. */ -typedef int (*rocprofiler_callback_tracing_kind_name_cb_t)( +typedef int (*rocprofiler_callback_tracing_kind_cb_t)( rocprofiler_service_callback_tracing_kind_t kind, - const char* kind_name, void* data); /** @@ -167,10 +166,9 @@ typedef int (*rocprofiler_callback_tracing_kind_name_cb_t)( * rocprofiler_service_callback_tracing_kind_t to string names. @see * rocprofiler_iterate_callback_tracing_kind_operation_names. */ -typedef int (*rocprofiler_callback_tracing_operation_name_cb_t)( +typedef int (*rocprofiler_callback_tracing_kind_operation_cb_t)( rocprofiler_service_callback_tracing_kind_t kind, uint32_t operation, - const char* operation_name, void* data); /** @@ -231,6 +229,47 @@ rocprofiler_configure_callback_tracing_service(rocprofiler_context_id_t context_ rocprofiler_callback_tracing_cb_t callback, void* callback_args); +/** + * @brief Query the name of the callback tracing kind. The name retrieved from this function is a + * string literal that is encoded in the read-only section of the binary (i.e. it is always + * "allocated" and never "deallocated"). + * + * @param kind [in] Callback tracing domain + * @param name [out] If non-null and the name is a constant string that does not require dynamic + * allocation, this paramter will be set to the address of the string literal, otherwise it will + * be set to nullptr + * @param name_len [out] If non-null, this will be assigned the length of the name (regardless of + * the name is a constant string or requires dynamic allocation) + * @return rocprofiler_status_t + */ +rocprofiler_status_t +rocprofiler_query_callback_tracing_kind_name(rocprofiler_service_callback_tracing_kind_t kind, + const char** name, + uint64_t* name_len) ROCPROFILER_API; + +/** + * @brief Query the name of the callback tracing kind. The name retrieved from this function is a + * string literal that is encoded in the read-only section of the binary (i.e. it is always + * "allocated" and never "deallocated"). + * + * @param kind [in] Callback tracing domain + * @param operation [in] Enumeration id value which maps to a specific API function or event type + * @param name [out] If non-null and the name is a constant string that does not require dynamic + * allocation, this paramter will be set to the address of the string literal, otherwise it will + * be set to nullptr + * @param name_len [out] If non-null, this will be assigned the length of the name (regardless of + * the name is a constant string or requires dynamic allocation) + * @return rocprofiler_status_t Returns @ref ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND if the + * domain id is not valid. Returns @ref ROCPROFILER_STATUS_SUCCESS for a valid domain regardless if + * there is a constant string or not. + */ +rocprofiler_status_t +rocprofiler_query_callback_tracing_kind_operation_name( + rocprofiler_service_callback_tracing_kind_t kind, + uint32_t operation, + const char** name, + uint64_t* name_len) ROCPROFILER_API; + /** * @brief Iterate over all the mappings of the callback tracing kinds and get a callback with the id * mapped to a constant string. The strings provided in the arg will be valid pointers for the @@ -240,11 +279,16 @@ rocprofiler_configure_callback_tracing_service(rocprofiler_context_id_t context_ * @param [in] callback Callback function invoked for each enumeration value in @ref * rocprofiler_service_callback_tracing_kind_t with the exception of the `NONE` and `LAST` values. * @param [in] data User data passed back into the callback + * @return rocprofiler_status_t Returns @ref ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND on an invalid + * domain id. Returns @ref ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND if the operation number is + * not recognized for the given domain. Returns @ref ROCPROFILER_STATUS_ERROR_NOT_IMPLEMENTED if + * rocprofiler does not support providing the operation name within this domain. Returns @ref + * ROCPROFILER_STATUS_SUCCESS for valid domain and operation regardless of whether there is a + * constant string or not. */ rocprofiler_status_t ROCPROFILER_API -rocprofiler_iterate_callback_tracing_kind_names( - rocprofiler_callback_tracing_kind_name_cb_t callback, - void* data) ROCPROFILER_NONNULL(1); +rocprofiler_iterate_callback_tracing_kinds(rocprofiler_callback_tracing_kind_cb_t callback, + void* data) ROCPROFILER_NONNULL(1); /** * @brief Iterates over all the mappings of the operations for a given @ref @@ -259,9 +303,9 @@ rocprofiler_iterate_callback_tracing_kind_names( * @param [in] data User data passed back into the callback */ rocprofiler_status_t ROCPROFILER_API -rocprofiler_iterate_callback_tracing_kind_operation_names( +rocprofiler_iterate_callback_tracing_kind_operations( rocprofiler_service_callback_tracing_kind_t kind, - rocprofiler_callback_tracing_operation_name_cb_t callback, + rocprofiler_callback_tracing_kind_operation_cb_t callback, void* data) ROCPROFILER_NONNULL(2); /** @@ -274,7 +318,7 @@ rocprofiler_iterate_callback_tracing_kind_operation_names( * @param[in] user_data Data to be passed to each invocation of the callback */ rocprofiler_status_t ROCPROFILER_API -rocprofiler_iterate_callback_tracing_operation_args( +rocprofiler_iterate_callback_tracing_kind_operation_args( rocprofiler_callback_tracing_record_t record, rocprofiler_callback_tracing_operation_args_cb_t callback, void* user_data) ROCPROFILER_NONNULL(2); diff --git a/source/include/rocprofiler/fwd.h b/source/include/rocprofiler/fwd.h index f7ee42866c..b8a87b0973 100644 --- a/source/include/rocprofiler/fwd.h +++ b/source/include/rocprofiler/fwd.h @@ -51,7 +51,7 @@ typedef enum // NOLINT(performance-enum-size) ROCPROFILER_STATUS_ERROR, ///< Generalized error ROCPROFILER_STATUS_ERROR_CONTEXT_NOT_FOUND, ///< No valid context for given context id ROCPROFILER_STATUS_ERROR_BUFFER_NOT_FOUND, ///< No valid buffer for given buffer id - ROCPROFILER_STATUS_ERROR_DOMAIN_NOT_FOUND, ///< Domain identifier is invalid + ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND, ///< Kind identifier is invalid ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND, ///< Operation identifier is invalid for domain ROCPROFILER_STATUS_ERROR_THREAD_NOT_FOUND, ///< No valid thread for given thread id ROCPROFILER_STATUS_ERROR_AGENT_NOT_FOUND, ///< Agent identifier not found diff --git a/source/lib/rocprofiler/buffer_tracing.cpp b/source/lib/rocprofiler/buffer_tracing.cpp index 935a065c1c..7b5000c92e 100644 --- a/source/lib/rocprofiler/buffer_tracing.cpp +++ b/source/lib/rocprofiler/buffer_tracing.cpp @@ -40,6 +40,46 @@ return _status; \ } +namespace rocprofiler +{ +namespace buffer_tracing +{ +namespace +{ +#define ROCPROFILER_BUFFER_TRACING_KIND_STRING(CODE) \ + template <> \ + struct buffer_tracing_kind_string \ + { \ + static constexpr auto value = \ + std::pair{#CODE, std::string_view{#CODE}.length()}; \ + }; + +template +struct buffer_tracing_kind_string; + +ROCPROFILER_BUFFER_TRACING_KIND_STRING(NONE) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(HSA_API) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(HIP_API) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(MARKER_API) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(MEMORY_COPY) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(KERNEL_DISPATCH) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(PAGE_MIGRATION) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(SCRATCH_MEMORY) +ROCPROFILER_BUFFER_TRACING_KIND_STRING(EXTERNAL_CORRELATION) + +template +std::pair +get_kind_name(rocprofiler_service_buffer_tracing_kind_t kind, std::index_sequence) +{ + if(kind == Idx) return buffer_tracing_kind_string::value; + // recursion until tail empty + if constexpr(sizeof...(Tail) > 0) return get_kind_name(kind, std::index_sequence{}); + return {nullptr, 0}; +} +} // namespace +} // namespace buffer_tracing +} // namespace rocprofiler + extern "C" { rocprofiler_status_t rocprofiler_configure_buffer_tracing_service(rocprofiler_context_id_t context_id, @@ -86,51 +126,66 @@ rocprofiler_configure_buffer_tracing_service(rocprofiler_context_id_t } rocprofiler_status_t -rocprofiler_iterate_buffer_tracing_kind_names(rocprofiler_buffer_tracing_kind_name_cb_t callback, - void* data) +rocprofiler_query_buffer_tracing_kind_name(rocprofiler_service_buffer_tracing_kind_t kind, + const char** name, + uint64_t* name_len) { - // TODO(jrmadsen): need to add for other kinds - size_t n = 0; - bool premature = false; - using pair_t = std::pair; - for(auto [eitr, sitr] : { - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API, "HSA_API"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_HIP_API, "HIP_API"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_MARKER_API, "MARKER_API"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_MEMORY_COPY, "MEMORY_COPY"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_KERNEL_DISPATCH, "KERNEL_DISPATCH"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_PAGE_MIGRATION, "PAGE_MIGRATION"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_SCRATCH_MEMORY, "SCRATCH_MEMORY"}, - pair_t{ROCPROFILER_SERVICE_BUFFER_TRACING_EXTERNAL_CORRELATION, "EXTERNAL_CORRELATION"}, - }) + auto&& val = rocprofiler::buffer_tracing::get_kind_name( + kind, std::make_index_sequence{}); + + if(name) *name = val.first; + if(name_len) *name_len = val.second; + + return (val.first) ? ROCPROFILER_STATUS_SUCCESS : ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; +} + +rocprofiler_status_t +rocprofiler_query_buffer_tracing_kind_operation_name(rocprofiler_service_buffer_tracing_kind_t kind, + uint32_t operation, + const char** name, + uint64_t* name_len) +{ + if(kind < ROCPROFILER_SERVICE_BUFFER_TRACING_NONE || + kind >= ROCPROFILER_SERVICE_BUFFER_TRACING_LAST) + return ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; + + if(kind == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) { - auto _success = callback(eitr, sitr, data); - if(_success != 0) + const auto* val = rocprofiler::hsa::name_by_id(operation); + + if(!val) { - premature = true; - break; + if(name) *name = nullptr; + if(name_len) *name_len = 0; + + return ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND; } - ++n; + + if(name) *name = val; + if(name_len) *name_len = strnlen(val, 4096); + + return ROCPROFILER_STATUS_SUCCESS; } -#if defined(ROCPROFILER_CI) - if(!premature) + return ROCPROFILER_STATUS_ERROR_NOT_IMPLEMENTED; +} + +rocprofiler_status_t +rocprofiler_iterate_buffer_tracing_kinds(rocprofiler_buffer_tracing_kind_cb_t callback, void* data) +{ + for(uint32_t i = 0; i < ROCPROFILER_SERVICE_BUFFER_TRACING_LAST; ++i) { - LOG_ASSERT(n == ROCPROFILER_SERVICE_BUFFER_TRACING_LAST - 1) - << " :: new enumeration value added. Update this function"; + auto _success = callback(static_cast(i), data); + if(_success != 0) break; } -#else - (void) n; - (void) premature; -#endif return ROCPROFILER_STATUS_SUCCESS; } rocprofiler_status_t -rocprofiler_iterate_buffer_tracing_kind_operation_names( +rocprofiler_iterate_buffer_tracing_kind_operations( rocprofiler_service_buffer_tracing_kind_t kind, - rocprofiler_buffer_tracing_operation_name_cb_t callback, + rocprofiler_buffer_tracing_kind_operation_cb_t callback, void* data) { if(kind == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) @@ -138,7 +193,7 @@ rocprofiler_iterate_buffer_tracing_kind_operation_names( auto ops = rocprofiler::hsa::get_ids(); for(const auto& itr : ops) { - auto _success = callback(kind, itr, rocprofiler::hsa::name_by_id(itr), data); + auto _success = callback(kind, itr, data); if(_success != 0) break; } return ROCPROFILER_STATUS_SUCCESS; diff --git a/source/lib/rocprofiler/callback_tracing.cpp b/source/lib/rocprofiler/callback_tracing.cpp index 9ea9134af7..e2590fe650 100644 --- a/source/lib/rocprofiler/callback_tracing.cpp +++ b/source/lib/rocprofiler/callback_tracing.cpp @@ -20,6 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#include #include #include "lib/rocprofiler/context/context.hpp" @@ -38,6 +39,43 @@ return _status; \ } +namespace rocprofiler +{ +namespace callback_tracing +{ +namespace +{ +#define ROCPROFILER_CALLBACK_TRACING_KIND_STRING(CODE) \ + template <> \ + struct callback_tracing_kind_string \ + { \ + static constexpr auto value = \ + std::pair{#CODE, std::string_view{#CODE}.length()}; \ + }; + +template +struct callback_tracing_kind_string; + +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(NONE) +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(HSA_API) +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(HIP_API) +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(MARKER_API) +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(CODE_OBJECT) +ROCPROFILER_CALLBACK_TRACING_KIND_STRING(KERNEL_DISPATCH) + +template +std::pair +get_kind_name(rocprofiler_service_callback_tracing_kind_t kind, std::index_sequence) +{ + if(kind == Idx) return callback_tracing_kind_string::value; + // recursion until tail empty + if constexpr(sizeof...(Tail) > 0) return get_kind_name(kind, std::index_sequence{}); + return {nullptr, 0}; +} +} // namespace +} // namespace callback_tracing +} // namespace rocprofiler + extern "C" { rocprofiler_status_t rocprofiler_configure_callback_tracing_service(rocprofiler_context_id_t context_id, @@ -79,49 +117,68 @@ rocprofiler_configure_callback_tracing_service(rocprofiler_context_id_t context_ } rocprofiler_status_t -rocprofiler_iterate_callback_tracing_kind_names( - rocprofiler_callback_tracing_kind_name_cb_t callback, - void* data) +rocprofiler_query_callback_tracing_kind_name(rocprofiler_service_callback_tracing_kind_t kind, + const char** name, + uint64_t* name_len) { - // TODO(jrmadsen): need to add for other kinds - size_t n = 0; - bool premature = false; - using pair_t = std::pair; - for(auto [eitr, sitr] : { - pair_t{ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API, "HSA_API"}, - pair_t{ROCPROFILER_SERVICE_CALLBACK_TRACING_HIP_API, "HIP_API"}, - pair_t{ROCPROFILER_SERVICE_CALLBACK_TRACING_MARKER_API, "MARKER_API"}, - pair_t{ROCPROFILER_SERVICE_CALLBACK_TRACING_CODE_OBJECT, "CODE_OBJECT"}, - pair_t{ROCPROFILER_SERVICE_CALLBACK_TRACING_KERNEL_DISPATCH, "KERNEL_DISPATCH"}, - }) + auto&& val = rocprofiler::callback_tracing::get_kind_name( + kind, std::make_index_sequence{}); + + if(name) *name = val.first; + if(name_len) *name_len = val.second; + + return (val.first) ? ROCPROFILER_STATUS_SUCCESS : ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; +} + +rocprofiler_status_t +rocprofiler_query_callback_tracing_kind_operation_name( + rocprofiler_service_callback_tracing_kind_t kind, + uint32_t operation, + const char** name, + uint64_t* name_len) +{ + if(kind < ROCPROFILER_SERVICE_CALLBACK_TRACING_NONE || + kind >= ROCPROFILER_SERVICE_CALLBACK_TRACING_LAST) + return ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; + + if(kind == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) { - auto _success = callback(eitr, sitr, data); - if(_success != 0) + const auto* val = rocprofiler::hsa::name_by_id(operation); + + if(!val) { - premature = true; - break; + if(name) *name = nullptr; + if(name_len) *name_len = 0; + + return ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND; } - ++n; + + if(name) *name = val; + if(name_len) *name_len = strnlen(val, 4096); + + return ROCPROFILER_STATUS_SUCCESS; } -#if defined(ROCPROFILER_CI) - if(!premature) + return ROCPROFILER_STATUS_ERROR_NOT_IMPLEMENTED; +} + +rocprofiler_status_t +rocprofiler_iterate_callback_tracing_kinds(rocprofiler_callback_tracing_kind_cb_t callback, + void* data) +{ + for(uint32_t i = 0; i < ROCPROFILER_SERVICE_CALLBACK_TRACING_LAST; ++i) { - LOG_ASSERT(n == ROCPROFILER_SERVICE_CALLBACK_TRACING_LAST - 1) - << " :: new enumeration value added. Update this function"; + auto _success = callback(static_cast(i), data); + if(_success != 0) break; } -#else - (void) n; - (void) premature; -#endif return ROCPROFILER_STATUS_SUCCESS; } rocprofiler_status_t -rocprofiler_iterate_callback_tracing_kind_operation_names( +rocprofiler_iterate_callback_tracing_kind_operations( rocprofiler_service_callback_tracing_kind_t kind, - rocprofiler_callback_tracing_operation_name_cb_t callback, + rocprofiler_callback_tracing_kind_operation_cb_t callback, void* data) { if(kind == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) @@ -129,7 +186,7 @@ rocprofiler_iterate_callback_tracing_kind_operation_names( auto ops = rocprofiler::hsa::get_ids(); for(const auto& itr : ops) { - auto _success = callback(kind, itr, rocprofiler::hsa::name_by_id(itr), data); + auto _success = callback(kind, itr, data); if(_success != 0) break; } return ROCPROFILER_STATUS_SUCCESS; @@ -139,7 +196,7 @@ rocprofiler_iterate_callback_tracing_kind_operation_names( } rocprofiler_status_t -rocprofiler_iterate_callback_tracing_operation_args( +rocprofiler_iterate_callback_tracing_kind_operation_args( rocprofiler_callback_tracing_record_t record, rocprofiler_callback_tracing_operation_args_cb_t callback, void* user_data) diff --git a/source/lib/rocprofiler/context/domain.cpp b/source/lib/rocprofiler/context/domain.cpp index 56ec2bbd1b..5a9aa74a34 100644 --- a/source/lib/rocprofiler/context/domain.cpp +++ b/source/lib/rocprofiler/context/domain.cpp @@ -47,7 +47,7 @@ rocprofiler_status_t add_domain(domain_context& _cfg, DomainT _domain) { if(_domain <= domain_info::none || _domain >= domain_info::last) - return ROCPROFILER_STATUS_ERROR_DOMAIN_NOT_FOUND; + return ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; _cfg.domains |= (1 << _domain); return ROCPROFILER_STATUS_SUCCESS; @@ -58,7 +58,7 @@ rocprofiler_status_t add_domain_op(domain_context& _cfg, DomainT _domain, uint32_t _op) { if(_domain <= domain_info::none || _domain >= domain_info::last) - return ROCPROFILER_STATUS_ERROR_DOMAIN_NOT_FOUND; + return ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND; if(_op >= domain_info::padding) return ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND; diff --git a/source/lib/rocprofiler/rocprofiler.cpp b/source/lib/rocprofiler/rocprofiler.cpp index 221b825497..5e6f32c612 100644 --- a/source/lib/rocprofiler/rocprofiler.cpp +++ b/source/lib/rocprofiler/rocprofiler.cpp @@ -44,7 +44,7 @@ ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_SUCCESS, "Success") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR, "General error") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_CONTEXT_NOT_FOUND, "Context ID not found") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_BUFFER_NOT_FOUND, "Buffer ID not found") -ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_DOMAIN_NOT_FOUND, "Domain ID not found") +ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_KIND_NOT_FOUND, "Kind ID not found") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_OPERATION_NOT_FOUND, "Operation ID not found") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_THREAD_NOT_FOUND, "Thread ID not found") ROCPROFILER_STATUS_STRING(ROCPROFILER_STATUS_ERROR_CONTEXT_ERROR, "General context error") diff --git a/source/lib/rocprofiler/tests/registration.cpp b/source/lib/rocprofiler/tests/registration.cpp index 56e0850191..75e498ad02 100644 --- a/source/lib/rocprofiler/tests/registration.cpp +++ b/source/lib/rocprofiler/tests/registration.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #define ROCPROFILER_CALL(ARG, MSG) \ @@ -58,6 +60,7 @@ struct callback_data rocprofiler_callback_thread_t client_thread = {}; uint64_t client_workflow_count = {}; uint64_t client_callback_count = {}; + uint64_t client_elapsed = {}; int64_t current_depth = 0; int64_t max_depth = 0; }; @@ -68,48 +71,147 @@ struct agent_data std::vector agents = {}; }; -void -tool_tracing_callback(rocprofiler_callback_tracing_record_t record, - rocprofiler_user_data_t*, - void* client_data) +using callback_kind_names_t = std::map; +using callback_kind_operation_names_t = + std::map>; + +struct callback_name_info { - using name_map_t = std::unordered_map>; + callback_kind_names_t kind_names = {}; + callback_kind_operation_names_t operation_names = {}; +}; - auto* cb_data = static_cast(client_data); +auto +get_callback_tracing_names() +{ + auto cb_name_info = callback_name_info{}; + // + // callback for each kind operation + // + static auto tracing_kind_operation_cb = + [](rocprofiler_service_callback_tracing_kind_t kindv, uint32_t operation, void* data_v) { + auto* name_info_v = static_cast(data_v); - static auto name_map = []() { - auto outer_cb = [](rocprofiler_service_callback_tracing_kind_t kind_v, - const char* /*kind_name*/, - void* data_v) { - auto inner_cb = [](rocprofiler_service_callback_tracing_kind_t kind, - uint32_t operation, - const char* operation_name, - void* data) { - auto& mdata = *static_cast(data); - mdata[kind][operation] = operation_name; - return 0; - }; - - auto& mdata_v = *static_cast(data_v); - mdata_v.emplace(kind_v, std::unordered_map{}); - - rocprofiler_iterate_callback_tracing_kind_operation_names(kind_v, inner_cb, data_v); + if(kindv == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) + { + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_callback_tracing_kind_operation_name( + kindv, operation, &name, nullptr), + "query callback tracing kind operation name"); + if(name) name_info_v->operation_names[kindv][operation] = name; + } return 0; }; - auto tmp = name_map_t{}; - rocprofiler_iterate_callback_tracing_kind_names(outer_cb, static_cast(&tmp)); + // + // callback for each callback kind (i.e. domain) + // + static auto tracing_kind_cb = [](rocprofiler_service_callback_tracing_kind_t kind, void* data) { + // store the callback kind name + auto* name_info_v = static_cast(data); + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_callback_tracing_kind_name(kind, &name, nullptr), + "query callback tracing kind operation name"); + if(name) name_info_v->kind_names[kind] = name; - EXPECT_EQ(tmp.size(), ROCPROFILER_SERVICE_CALLBACK_TRACING_LAST - 1); - EXPECT_EQ(tmp.at(ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API).size(), - ROCPROFILER_HSA_API_ID_LAST); + if(kind == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API) + { + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kind_operations( + kind, tracing_kind_operation_cb, static_cast(data)), + "iterating callback tracing kind operations"); + } + return 0; + }; - return tmp; - }(); + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kinds(tracing_kind_cb, + static_cast(&cb_name_info)), + "iterating callback tracing kinds"); + + return cb_name_info; +} + +using buffer_kind_names_t = std::map; +using buffer_kind_operation_names_t = + std::map>; + +struct buffer_name_info +{ + buffer_kind_names_t kind_names = {}; + buffer_kind_operation_names_t operation_names = {}; +}; + +buffer_name_info +get_buffer_tracing_names() +{ + auto cb_name_info = buffer_name_info{}; + // + // callback for each kind operation + // + static auto tracing_kind_operation_cb = + [](rocprofiler_service_buffer_tracing_kind_t kindv, uint32_t operation, void* data_v) { + auto* name_info_v = static_cast(data_v); + + if(kindv == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) + { + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_buffer_tracing_kind_operation_name( + kindv, operation, &name, nullptr), + "query buffer tracing kind operation name"); + if(name) name_info_v->operation_names[kindv][operation] = name; + } + return 0; + }; + + // + // callback for each buffer kind (i.e. domain) + // + static auto tracing_kind_cb = [](rocprofiler_service_buffer_tracing_kind_t kind, void* data) { + // store the buffer kind name + auto* name_info_v = static_cast(data); + const char* name = nullptr; + ROCPROFILER_CALL(rocprofiler_query_buffer_tracing_kind_name(kind, &name, nullptr), + "query buffer tracing kind operation name"); + if(name) name_info_v->kind_names[kind] = name; + + if(kind == ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API) + { + ROCPROFILER_CALL(rocprofiler_iterate_buffer_tracing_kind_operations( + kind, tracing_kind_operation_cb, static_cast(data)), + "iterating buffer tracing kind operations"); + } + return 0; + }; + + ROCPROFILER_CALL(rocprofiler_iterate_buffer_tracing_kinds(tracing_kind_cb, + static_cast(&cb_name_info)), + "iterating buffer tracing kinds"); + + return cb_name_info; +} + +void +tool_tracing_callback(rocprofiler_callback_tracing_record_t record, + rocprofiler_user_data_t* user_data, + void* client_data) +{ + auto* cb_data = static_cast(client_data); + auto get_timestamp = []() { + return std::chrono::steady_clock::now().time_since_epoch().count(); + }; + + if(record.phase == ROCPROFILER_SERVICE_CALLBACK_PHASE_ENTER && cb_data->current_depth == 0) + { + user_data->value = get_timestamp(); + } + + static auto name_map = get_callback_tracing_names(); + + EXPECT_EQ(name_map.kind_names.size(), ROCPROFILER_SERVICE_CALLBACK_TRACING_LAST); + EXPECT_EQ(name_map.operation_names.at(ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API).size(), + ROCPROFILER_HSA_API_ID_LAST); std::cout << "[" << __FILE__ << ":" << __LINE__ << "] " - << name_map[record.kind][record.operation] << "\n" + << name_map.operation_names[record.kind][record.operation] << "\n" << std::flush; cb_data->client_callback_count++; @@ -151,7 +253,7 @@ tool_tracing_callback(rocprofiler_callback_tracing_record_t record, return 0; }; - ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_operation_args( + ROCPROFILER_CALL(rocprofiler_iterate_callback_tracing_kind_operation_args( record, info_data_cb, static_cast(&info_data_v)), "Failure iterating trace operation args"); if(record.kind == ROCPROFILER_SERVICE_CALLBACK_TRACING_HSA_API && @@ -159,7 +261,12 @@ tool_tracing_callback(rocprofiler_callback_tracing_record_t record, record.operation == ROCPROFILER_HSA_API_ID_hsa_shut_down)) { EXPECT_GT(info_data_v.num_args, 0) - << name_map[record.kind][record.operation] << info_data_v.arg_ss.str(); + << name_map.operation_names[record.kind][record.operation] << info_data_v.arg_ss.str(); + } + + if(record.phase == ROCPROFILER_SERVICE_CALLBACK_PHASE_EXIT && cb_data->current_depth == 0) + { + cb_data->client_elapsed += (get_timestamp() - user_data->value); } } @@ -171,36 +278,13 @@ tool_tracing_buffered(rocprofiler_context_id_t context, void* buffer_data, uint64_t drop_count) { - using name_map_t = std::unordered_map>; - - std::cout << __FUNCTION__ << "...\n" << std::endl; auto* cb_data = static_cast(buffer_data); - static auto name_map = []() { - auto tmp = name_map_t{}; - // - static auto tracing_kind_names_cb = [](rocprofiler_service_buffer_tracing_kind_t kind, - const char* /*kind_name*/, - void* data) { - auto tracing_operation_names_cb = [](rocprofiler_service_buffer_tracing_kind_t kindv, - uint32_t operation, - const char* operation_name, - void* data_v) { - (*static_cast(data_v))[kindv][operation] = operation_name; - return 0; - }; + static auto name_map = get_buffer_tracing_names(); - rocprofiler_iterate_buffer_tracing_kind_operation_names( - kind, tracing_operation_names_cb, data); - - return 0; - }; - - rocprofiler_iterate_buffer_tracing_kind_names(tracing_kind_names_cb, - static_cast(&tmp)); - return tmp; - }(); + EXPECT_EQ(name_map.kind_names.size(), ROCPROFILER_SERVICE_BUFFER_TRACING_LAST); + EXPECT_EQ(name_map.operation_names.at(ROCPROFILER_SERVICE_BUFFER_TRACING_HSA_API).size(), + ROCPROFILER_HSA_API_ID_LAST); auto v_records = std::vector{}; v_records.reserve(num_headers); @@ -230,9 +314,10 @@ tool_tracing_buffered(rocprofiler_context_id_t context, auto info = std::stringstream{}; info << "tid=" << record->thread_id << ", context=" << context.handle << ", buffer_id=" << buffer_id.handle << ", cid=" << record->correlation_id.internal - << ", kind=" << record->kind << ", operation=" << record->operation - << ", drop_count=" << drop_count << ", start=" << record->start_timestamp - << ", stop=" << record->end_timestamp; + << ", kind=" << name_map.kind_names.at(record->kind) << "(" << record->kind + << "), operation=" << name_map.operation_names.at(record->kind).at(record->operation) + << "(" << record->operation << "), drop_count=" << drop_count + << ", start=" << record->start_timestamp << ", stop=" << record->end_timestamp; static int64_t last_corr_id = -1; auto corr_id = static_cast(record->correlation_id.internal); @@ -295,6 +380,7 @@ TEST(rocprofiler_lib, callback_registration_lambda_with_result) using hsa_iterate_agents_cb_t = hsa_status_t (*)(hsa_agent_t, void*); auto cmd_line = rocprofiler::common::read_command_line(getpid()); + ASSERT_FALSE(cmd_line.empty()); static init_func_t tool_init = [](rocprofiler_client_finalize_t fini_func, @@ -360,6 +446,10 @@ TEST(rocprofiler_lib, callback_registration_lambda_with_result) return &cfg_result; }; + auto get_timestamp = []() { + return std::chrono::steady_clock::now().time_since_epoch().count(); + }; + auto ctx = rocprofiler_context_id_t{}; EXPECT_NE(rocprofiler_create_context(&ctx), ROCPROFILER_STATUS_SUCCESS); EXPECT_EQ(rocprofiler_force_configure(rocp_init), ROCPROFILER_STATUS_SUCCESS); @@ -377,14 +467,26 @@ TEST(rocprofiler_lib, callback_registration_lambda_with_result) return status; }; - auto _agent_data = agent_data{}; hsa_init(); - hsa_status_t itr_status = hsa_iterate_agents(agent_cb, static_cast(&_agent_data)); + auto _agent_data = agent_data{}; + auto begin_ts = get_timestamp(); + hsa_status_t itr_status = hsa_iterate_agents(agent_cb, static_cast(&_agent_data)); + auto end_ts = get_timestamp(); + auto elapsed = (end_ts - begin_ts); EXPECT_EQ(itr_status, HSA_STATUS_SUCCESS); EXPECT_GT(_agent_data.agent_count, 0); EXPECT_EQ(_agent_data.agent_count, _agent_data.agents.size()); +#if !defined(__OPTIMIZE__) || (defined(CODECOV) && CODECOV > 0) + EXPECT_GT(cb_data.client_elapsed, 0); + EXPECT_GT(elapsed, 0); +#else + decltype(elapsed) elapsed_tolerance = 0.25 * elapsed; + EXPECT_NEAR(elapsed, cb_data.client_elapsed, elapsed_tolerance) + << "it is possible this failed due to noise on the machine"; +#endif + ASSERT_NE(cb_data.client_id, nullptr); ASSERT_NE(cb_data.client_fini_func, nullptr);