diff --git a/inc/ext/prof_protocol.h b/inc/ext/prof_protocol.h index 65cf616b92..14bc81cb23 100644 --- a/inc/ext/prof_protocol.h +++ b/inc/ext/prof_protocol.h @@ -26,9 +26,10 @@ THE SOFTWARE. // Traced API domains typedef enum { ACTIVITY_DOMAIN_HSA_API = 0, // HSA domain - ACTIVITY_DOMAIN_HCC_OPS = 1, // HCC domain - ACTIVITY_DOMAIN_HIP_API = 2, // HIP domain - ACTIVITY_DOMAIN_NUMBER = 3 + ACTIVITY_DOMAIN_HSA_OPS = 1, // HSA AYNC domain + ACTIVITY_DOMAIN_HCC_OPS = 2, // HCC domain + ACTIVITY_DOMAIN_HIP_API = 3, // HIP domain + ACTIVITY_DOMAIN_NUMBER = 4 } activity_domain_t; // API calback type diff --git a/inc/roctracer_hsa.h b/inc/roctracer_hsa.h index 7eb2c5b92c..de4f1f9d1c 100644 --- a/inc/roctracer_hsa.h +++ b/inc/roctracer_hsa.h @@ -34,6 +34,10 @@ THE SOFTWARE. namespace roctracer { namespace hsa_support { +enum { + HSA_OP_ID_async_copy = 0 +}; + template class CbTable { public: @@ -68,8 +72,16 @@ class CbTable { extern CoreApiTable CoreApiTable_saved; extern AmdExtTable AmdExtTable_saved; extern ImageExtTable ImageExtTable_saved; + +struct ops_properties_t { + activity_async_callback_t async_copy_callback_fun; + void* async_copy_callback_arg; }; -}; + +}; // namespace hsa_support + +typedef hsa_support::ops_properties_t hsa_ops_properties_t; +}; // namespace roctracer inline std::ostream& operator<< (std::ostream& out, const hsa_callback_data_t& v) { out << ""; return out; } inline std::ostream& operator<< (std::ostream &out, const hsa_signal_t& v) { out << "" << std::dec; return out; } diff --git a/src/core/roctracer.cpp b/src/core/roctracer.cpp index 95ad920981..bba7b1b69c 100644 --- a/src/core/roctracer.cpp +++ b/src/core/roctracer.cpp @@ -89,18 +89,13 @@ namespace roctracer { decltype(hsa_amd_memory_async_copy)* hsa_amd_memory_async_copy_fn; decltype(hsa_amd_memory_async_copy_rect)* hsa_amd_memory_async_copy_rect_fn; -// Profiling results output dir -const char* result_prefix = NULL; -// Global results file handle -FILE* result_file_handle = NULL; -// True if a result file is opened -bool result_file_opened = false; - namespace hsa_support { // callbacks table cb_table_t cb_table; -// activity enabled -bool enabled = false;; +// asyc copy activity callback +activity_async_callback_t async_copy_callback_fun = NULL; +void* async_copy_callback_arg = NULL; +bool async_copy_callback_enabled = false; // Table of function pointers to HSA Core Runtime CoreApiTable CoreApiTable_saved{}; // Table of function pointers to AMD extensions @@ -376,7 +371,15 @@ void HCC_AsyncActivityCallback(uint32_t op_id, void* record, void* arg) { bool hsa_async_copy_handler(hsa_signal_value_t value, void* arg) { ::proxy::Tracker::entry_t* entry = reinterpret_cast<::proxy::Tracker::entry_t*>(arg); - fprintf(result_file_handle, "%lu:%lu async-copy%lu\n", entry->record->begin, entry->record->end, entry->index); + + activity_record_t record{}; + record.domain = ACTIVITY_DOMAIN_HSA_OPS; // activity domain id + record.correlation_id = entry->index; // activity ID + record.begin_ns = entry->record->begin; // host begin timestamp + record.end_ns = entry->record->end; // host end timestamp + record.device_id = 0; // device id + + hsa_support::async_copy_callback_fun(hsa_support::HSA_OP_ID_async_copy, &record, hsa_support::async_copy_callback_arg); return false; } @@ -386,7 +389,7 @@ hsa_status_t hsa_amd_memory_async_copy_interceptor( const hsa_signal_t* dep_signals, hsa_signal_t completion_signal) { hsa_status_t status = HSA_STATUS_SUCCESS; - if (hsa_support::enabled) { + if (hsa_support::async_copy_callback_enabled) { ::proxy::Tracker* tracker = &::proxy::Tracker::Instance(); ::proxy::Tracker::entry_t* tracker_entry = tracker->Alloc(hsa_agent_t{}, completion_signal); status = hsa_amd_memory_async_copy_fn(dst, dst_agent, src, @@ -412,7 +415,7 @@ hsa_status_t hsa_amd_memory_async_copy_rect_interceptor( hsa_signal_t completion_signal) { hsa_status_t status = HSA_STATUS_SUCCESS; - if (hsa_support::enabled) { + if (hsa_support::async_copy_callback_enabled) { ::proxy::Tracker* tracker = &::proxy::Tracker::Instance(); ::proxy::Tracker::entry_t* tracker_entry = tracker->Alloc(hsa_agent_t{}, completion_signal); status = hsa_amd_memory_async_copy_rect_fn(dst, dst_offset, src, @@ -511,9 +514,10 @@ PUBLIC_API roctracer_status_t roctracer_op_code( static inline uint32_t get_op_num(const uint32_t& domain) { switch (domain) { + case ACTIVITY_DOMAIN_HSA_OPS: return 1; + case ACTIVITY_DOMAIN_HSA_API: return HSA_API_ID_NUMBER; case ACTIVITY_DOMAIN_HCC_OPS: return hc::HSA_OP_ID_NUMBER; case ACTIVITY_DOMAIN_HIP_API: return HIP_API_ID_NUMBER; - case ACTIVITY_DOMAIN_HSA_API: return HSA_API_ID_NUMBER; default: EXC_RAISING(ROCTRACER_STATUS_BAD_DOMAIN, "invalid domain ID(" << domain << ")"); } @@ -528,6 +532,7 @@ static void roctracer_enable_callback_impl( void* user_data) { switch (domain) { + case ACTIVITY_DOMAIN_HSA_OPS: break; case ACTIVITY_DOMAIN_HSA_API: { roctracer::hsa_support::cb_table.set(op, callback, user_data); break; @@ -583,6 +588,7 @@ static void roctracer_disable_callback_impl( uint32_t op) { switch (domain) { + case ACTIVITY_DOMAIN_HSA_OPS: break; case ACTIVITY_DOMAIN_HSA_API: break; case ACTIVITY_DOMAIN_HCC_OPS: break; case ACTIVITY_DOMAIN_HIP_API: { @@ -667,10 +673,11 @@ static void roctracer_enable_activity_impl( { if (pool == NULL) pool = roctracer_default_pool(); switch (domain) { - case ACTIVITY_DOMAIN_HSA_API: { - roctracer::hsa_support::enabled = true; + case ACTIVITY_DOMAIN_HSA_OPS: { + roctracer::hsa_support::async_copy_callback_enabled = true; break; } + case ACTIVITY_DOMAIN_HSA_API: break; case ACTIVITY_DOMAIN_HCC_OPS: { if (roctracer::HccLoader::GetRef() == NULL) { roctracer::HccLoader::Instance().InitActivityCallback((void*)roctracer::HCC_ActivityIdCallback, @@ -728,10 +735,11 @@ static void roctracer_disable_activity_impl( uint32_t op) { switch (domain) { - case ACTIVITY_DOMAIN_HSA_API: { - roctracer::hsa_support::enabled = false; + case ACTIVITY_DOMAIN_HSA_OPS: { + roctracer::hsa_support::async_copy_callback_enabled = false; break; } + case ACTIVITY_DOMAIN_HSA_API: break; case ACTIVITY_DOMAIN_HCC_OPS: { const bool succ = roctracer::HccLoader::Instance().EnableActivityCallback(op, false); if (succ == false) HCC_EXC_RAISING(ROCTRACER_STATUS_HCC_OPS_ERR, "HCC::EnableActivityCallback(NULL) error domain(" << domain << ") op(" << op << ")"); @@ -787,12 +795,20 @@ PUBLIC_API roctracer_status_t roctracer_flush_activity(roctracer_pool_t* pool) { // Set properties PUBLIC_API roctracer_status_t roctracer_set_properties( roctracer_domain_t domain, - void* propertes) + void* properties) { API_METHOD_PREFIX switch (domain) { + case ACTIVITY_DOMAIN_HSA_OPS: { + // HSA OPS properties + roctracer::hsa_ops_properties_t* ops_properties = reinterpret_cast(properties); + roctracer::hsa_support::async_copy_callback_fun = ops_properties->async_copy_callback_fun; + roctracer::hsa_support::async_copy_callback_arg = ops_properties->async_copy_callback_arg; + break; + } case ACTIVITY_DOMAIN_HSA_API: { - HsaApiTable* table = reinterpret_cast(propertes); + // HSA API properties + HsaApiTable* table = reinterpret_cast(properties); roctracer::hsa_support::intercept_CoreApiTable(table->core_); roctracer::hsa_support::intercept_AmdExtTable(table->amd_ext_); roctracer::hsa_support::intercept_ImageExtTable(table->image_ext_); @@ -810,32 +826,6 @@ PUBLIC_API roctracer_status_t roctracer_set_properties( // HSA-runtime tool on-load method PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, const char* const* failed_tool_names) { - // Output file - roctracer::result_prefix = getenv("ROCP_OUTPUT_DIR"); - if (roctracer::result_prefix != NULL) { - DIR* dir = opendir(roctracer::result_prefix); - if (dir == NULL) { - std::ostringstream errmsg; - errmsg << "ROCTracer: Cannot open output directory '" << roctracer::result_prefix << "'"; - perror(errmsg.str().c_str()); - abort(); - } - std::ostringstream oss; - oss << roctracer::result_prefix << "/trace_async_copy.txt"; - roctracer::result_file_handle = fopen(oss.str().c_str(), "w"); - if (roctracer::result_file_handle == NULL) { - std::ostringstream errmsg; - errmsg << "ROCTracer: fopen error, file '" << oss.str().c_str() << "'"; - perror(errmsg.str().c_str()); - abort(); - } - } else roctracer::result_file_handle = stdout; - - roctracer::result_file_opened = (roctracer::result_prefix != NULL) && (roctracer::result_file_handle != NULL); - - // initialize HSA tracing - roctracer_set_properties(ACTIVITY_DOMAIN_HSA_API, (void*)table); - // enabled HSA async-copy tracing hsa_status_t status = hsa_amd_profiling_async_copy_enable(true); if (status != HSA_STATUS_SUCCESS) EXC_ABORT(status, "hsa_amd_profiling_async_copy_enable"); diff --git a/test/tool/tracer_tool.cpp b/test/tool/tracer_tool.cpp index d7d658451a..7afd4400db 100644 --- a/test/tool/tracer_tool.cpp +++ b/test/tool/tracer_tool.cpp @@ -54,19 +54,21 @@ thread_local timestamp_t hip_begin_timestamp = 0; bool trace_hsa = false; bool trace_hip = false; -// Profiling results output dir -const char* result_prefix = NULL; -// Global results file handle -FILE* result_file_handle = NULL; -// True if a result file is opened -bool result_file_opened = false; +// Global output file handle +FILE* hsa_api_file_handle = NULL; +FILE* hsa_async_copy_file_handle = NULL; +FILE* hip_api_file_handle = NULL; +FILE* hcc_activity_file_handle = NULL; static inline uint32_t GetPid() { return syscall(__NR_getpid); } static inline uint32_t GetTid() { return syscall(__NR_gettid); } // Error handler void fatal(const std::string msg) { - fflush(result_file_handle); + fflush(hsa_api_file_handle); + fflush(hsa_async_copy_file_handle); + fflush(hip_api_file_handle); + fflush(hcc_activity_file_handle); fflush(stdout); fprintf(stderr, "%s\n\n", msg.c_str()); fflush(stderr); @@ -89,10 +91,18 @@ void hsa_api_callback( const timestamp_t end_timestamp = (cid == HSA_API_ID_hsa_shut_down) ? hsa_begin_timestamp : timer->timestamp_fn_ns(); std::ostringstream os; os << hsa_begin_timestamp << ":" << end_timestamp << " " << GetPid() << ":" << GetTid() << " " << hsa_api_data_pair_t(cid, *data); - fprintf(result_file_handle, "%s\n", os.str().c_str()); + fprintf(hsa_api_file_handle, "%s\n", os.str().c_str()); } } +void hsa_activity_callback( + uint32_t op, + activity_record_t* record, + void* arg) +{ + fprintf(hsa_async_copy_file_handle, "%lu:%lu async-copy%lu\n", record->begin_ns, record->end_ns, record->correlation_id); +} + void hip_api_callback( uint32_t domain, uint32_t cid, @@ -106,33 +116,33 @@ void hip_api_callback( hsa_begin_timestamp = timer->timestamp_fn_ns(); } else { const timestamp_t end_timestamp = timer->timestamp_fn_ns(); - fprintf(result_file_handle, "%lu:%lu %u:%u %s(", hsa_begin_timestamp, end_timestamp, GetPid(), GetTid(), roctracer_op_string(ACTIVITY_DOMAIN_HIP_API, cid, 0)); + fprintf(hip_api_file_handle, "%lu:%lu %u:%u %s(", hsa_begin_timestamp, end_timestamp, GetPid(), GetTid(), roctracer_op_string(ACTIVITY_DOMAIN_HIP_API, cid, 0)); switch (cid) { case HIP_API_ID_hipMemcpy: - fprintf(result_file_handle, "dst(%p) src(%p) size(0x%x) kind(%u)", + fprintf(hip_api_file_handle, "dst(%p) src(%p) size(0x%x) kind(%u)", data->args.hipMemcpy.dst, data->args.hipMemcpy.src, (uint32_t)(data->args.hipMemcpy.sizeBytes), (uint32_t)(data->args.hipMemcpy.kind)); break; case HIP_API_ID_hipMalloc: - fprintf(result_file_handle, "ptr(0x%p) size(0x%x)", + fprintf(hip_api_file_handle, "ptr(0x%p) size(0x%x)", *(data->args.hipMalloc.ptr), (uint32_t)(data->args.hipMalloc.size)); break; case HIP_API_ID_hipFree: - fprintf(result_file_handle, "ptr(%p)", + fprintf(hip_api_file_handle, "ptr(%p)", data->args.hipFree.ptr); break; case HIP_API_ID_hipModuleLaunchKernel: - fprintf(result_file_handle, "kernel(\"%s\") stream(%p)", + fprintf(hip_api_file_handle, "kernel(\"%s\") stream(%p)", hipKernelNameRef(data->args.hipModuleLaunchKernel.f), data->args.hipModuleLaunchKernel.stream); break; default: break; } - fprintf(result_file_handle, ")\n"); fflush(result_file_handle); + fprintf(hip_api_file_handle, ")\n"); fflush(hip_api_file_handle); } } @@ -142,22 +152,22 @@ void hcc_activity_callback(const char* begin, const char* end, void* arg) { const roctracer_record_t* record = reinterpret_cast(begin); const roctracer_record_t* end_record = reinterpret_cast(end); - fprintf(result_file_handle, "\tActivity records:\n"); fflush(result_file_handle); + fprintf(hcc_activity_file_handle, "\tActivity records:\n"); fflush(hcc_activity_file_handle); while (record < end_record) { const char * name = roctracer_op_string(record->domain, record->op, record->kind); - fprintf(result_file_handle, "\t%s\tcorrelation_id(%lu) time_ns(%lu:%lu)", + fprintf(hcc_activity_file_handle, "\t%s\tcorrelation_id(%lu) time_ns(%lu:%lu)", name, record->correlation_id, record->begin_ns, record->end_ns ); if (record->domain == ACTIVITY_DOMAIN_HIP_API) { - fprintf(result_file_handle, " process_id(%u) thread_id(%u)", + fprintf(hcc_activity_file_handle, " process_id(%u) thread_id(%u)", record->process_id, record->thread_id ); } else if (record->domain == ACTIVITY_DOMAIN_HCC_OPS) { - fprintf(result_file_handle, " device_id(%d) queue_id(%lu)", + fprintf(hcc_activity_file_handle, " device_id(%d) queue_id(%lu)", record->device_id, record->queue_id ); @@ -165,9 +175,9 @@ void hcc_activity_callback(const char* begin, const char* end, void* arg) { fprintf(stderr, "Bad domain %d\n", record->domain); abort(); } - if (record->op == hc::HSA_OP_ID_COPY) fprintf(result_file_handle, " bytes(0x%zx)", record->bytes); - fprintf(result_file_handle, "\n"); - fflush(result_file_handle); + if (record->op == hc::HSA_OP_ID_COPY) fprintf(hcc_activity_file_handle, " bytes(0x%zx)", record->bytes); + fprintf(hcc_activity_file_handle, "\n"); + fflush(hcc_activity_file_handle); ROCTRACER_CALL(roctracer_next_record(record, &record)); } } @@ -218,6 +228,23 @@ int get_xml_array(const xml::Xml::level_t* node, const std::string& field, const return parse_iter; } +// Open output file +FILE* open_output_file(const char* prefix, const char* name) { + FILE* file_handle = NULL; + if (prefix != NULL) { + std::ostringstream oss; + oss << prefix << "/" << name; + file_handle = fopen(oss.str().c_str(), "w"); + if (file_handle == NULL) { + std::ostringstream errmsg; + errmsg << "ROCTracer: fopen error, file '" << oss.str().c_str() << "'"; + perror(errmsg.str().c_str()); + abort(); + } + } else file_handle = stdout; + return file_handle; +} + // HSA-runtime tool on-load method extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, const char* const* failed_tool_names) { @@ -229,27 +256,16 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, trace_hip = (trace_domain == NULL) || (strncmp(trace_domain, "hip", 3) == 0); // Output file - result_prefix = getenv("ROCP_OUTPUT_DIR"); - if (result_prefix != NULL) { - DIR* dir = opendir(result_prefix); + const char* output_prefix = getenv("ROCP_OUTPUT_DIR"); + if (output_prefix != NULL) { + DIR* dir = opendir(output_prefix); if (dir == NULL) { std::ostringstream errmsg; - errmsg << "ROCTracer: Cannot open output directory '" << result_prefix << "'"; + errmsg << "ROCTracer: Cannot open output directory '" << output_prefix << "'"; perror(errmsg.str().c_str()); abort(); } - std::ostringstream oss; - oss << result_prefix << "/trace.txt"; - result_file_handle = fopen(oss.str().c_str(), "w"); - if (result_file_handle == NULL) { - std::ostringstream errmsg; - errmsg << "ROCTracer: fopen error, file '" << oss.str().c_str() << "'"; - perror(errmsg.str().c_str()); - abort(); - } - } else result_file_handle = stdout; - - result_file_opened = (result_prefix != NULL) && (result_file_handle != NULL); + } // API trace vector std::vector hsa_api_vec; @@ -294,6 +310,16 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, // Enable HSA API callbacks if (trace_hsa) { + hsa_api_file_handle = open_output_file(output_prefix, "hsa_api_trace.txt"); + hsa_async_copy_file_handle = open_output_file(output_prefix, "async_copy_trace.txt"); + + // initialize HSA tracing + roctracer_set_properties(ACTIVITY_DOMAIN_HSA_API, (void*)table); + roctracer::hsa_ops_properties_t ops_properties{ + reinterpret_cast(hsa_activity_callback), + NULL}; + roctracer_set_properties(ACTIVITY_DOMAIN_HSA_OPS, &ops_properties); + printf(" HSA-trace("); if (hsa_api_vec.size() != 0) { for (unsigned i = 0; i < hsa_api_vec.size(); ++i) { @@ -306,12 +332,15 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, } else { ROCTRACER_CALL(roctracer_enable_domain_callback(ACTIVITY_DOMAIN_HSA_API, hsa_api_callback, NULL)); } - ROCTRACER_CALL(roctracer_enable_domain_activity(ACTIVITY_DOMAIN_HSA_API)); + ROCTRACER_CALL(roctracer_enable_domain_activity(ACTIVITY_DOMAIN_HSA_OPS)); printf(")\n"); } // Enable HIP API callbacks/activity if (trace_hip) { + hip_api_file_handle = open_output_file(output_prefix, "hip_api_trace.txt"); + hcc_activity_file_handle = open_output_file(output_prefix, "hcc_ops_trace.txt"); + printf(" HIP-trace()\n"); // Allocating tracing pool roctracer_properties_t properties{}; @@ -330,10 +359,18 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, extern "C" PUBLIC_API void OnUnload() { if (trace_hsa) { ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API)); + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HSA_OPS)); + + fclose(hsa_api_file_handle); + fclose(hsa_async_copy_file_handle); } if (trace_hip) { ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HIP_API)); - ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HCC_OPS)); + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HIP_API)); + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HCC_OPS)); ROCTRACER_CALL(roctracer_close_pool()); + + fclose(hip_api_file_handle); + fclose(hcc_activity_file_handle); } }