diff --git a/projects/rocprofiler/inc/rocprofiler.h b/projects/rocprofiler/inc/rocprofiler.h index 91661635dc..6b595bc486 100644 --- a/projects/rocprofiler/inc/rocprofiler.h +++ b/projects/rocprofiler/inc/rocprofiler.h @@ -464,15 +464,15 @@ hsa_status_t rocprofiler_pool_flush( // HSA intercepting API // HSA callbacks ID enumeration -enum rocprofiler_hsa_cb_id_t { +typedef enum { ROCPROFILER_HSA_CB_ID_ALLOCATE = 0, // Memory allocate callback ROCPROFILER_HSA_CB_ID_DEVICE = 1, // Device assign callback ROCPROFILER_HSA_CB_ID_MEMCOPY = 2, // Memcopy callback ROCPROFILER_HSA_CB_ID_SUBMIT = 3 // Packet submit callback -}; +} rocprofiler_hsa_cb_id_t; // HSA callback data type -struct rocprofiler_hsa_callback_data_t { +typedef struct { union { struct { const void* ptr; // allocated area ptr @@ -500,7 +500,7 @@ struct rocprofiler_hsa_callback_data_t { uint32_t device_id; // id of device the packed is submitted to } submit; }; -}; +} rocprofiler_hsa_callback_data_t; // HSA callback function type typedef hsa_status_t (*rocprofiler_hsa_callback_fun_t)( @@ -509,12 +509,12 @@ typedef hsa_status_t (*rocprofiler_hsa_callback_fun_t)( void* arg); // [in/out] user passed data // HSA callbacks structure -struct rocprofiler_hsa_callbacks_t { +typedef struct { rocprofiler_hsa_callback_fun_t allocate; // memory allocate callback rocprofiler_hsa_callback_fun_t device; // agent assign callback rocprofiler_hsa_callback_fun_t memcopy; // memory copy callback rocprofiler_hsa_callback_fun_t submit; // packet submit callback -}; +} rocprofiler_hsa_callbacks_t; // Set callbacks. If the callback is NULL then it is disabled. // If callback returns a value that is not HSA_STATUS_SUCCESS the callback diff --git a/projects/rocprofiler/src/core/hsa_listener.h b/projects/rocprofiler/src/core/hsa_listener.h deleted file mode 100644 index 844e5b50d9..0000000000 --- a/projects/rocprofiler/src/core/hsa_listener.h +++ /dev/null @@ -1,47 +0,0 @@ -/****************************************************************************** -MIT License - -Copyright (c) 2018 ROCm Core Technology - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*******************************************************************************/ - -#ifndef _SRC_CORE_HSA_LISTENER_H -#define _SRC_CORE_HSA_LISTENER_H - -#include - -#include "util/exception.h" - -namespace rocprofiler { -extern decltype(hsa_queue_destroy)* hsa_queue_destroy_fn; -extern decltype(hsa_amd_queue_intercept_create)* hsa_amd_queue_intercept_create_fn; -extern decltype(hsa_amd_queue_intercept_register)* hsa_amd_queue_intercept_register_fn; - -class HsaListener { - public: - hsa_status_t SetCallbacks(rocprofiler_hsa_callbacks_t callbacks, void* data) { - } - - private: -}; - -} // namespace rocprofiler - -#endif // _SRC_CORE_HSA_LISTENER_H diff --git a/projects/rocprofiler/src/core/intercept_queue.h b/projects/rocprofiler/src/core/intercept_queue.h index cfacdc6612..8cc202b48d 100644 --- a/projects/rocprofiler/src/core/intercept_queue.h +++ b/projects/rocprofiler/src/core/intercept_queue.h @@ -134,10 +134,16 @@ class InterceptQueue { const packet_t* packet = &packets_arr[j]; const hsa_kernel_dispatch_packet_t* dispatch_packet = reinterpret_cast(packet); + + uint64_t kernel_object = dispatch_packet->kernel_object; + const amd_kernel_code_t* kernel_code = GetKernelCode(kernel_object); + const char* kernel_name = (GetHeaderType(packet) == HSA_PACKET_TYPE_KERNEL_DISPATCH) ? + QueryKernelName(kernel_object, kernel_code) : NULL; + + // Prepareing submit callback data rocprofiler_hsa_callback_data_t data{}; data.submit.packet = (void*)packet; - data.submit.kernel_name = - (GetHeaderType(packet) == HSA_PACKET_TYPE_KERNEL_DISPATCH) ? GetKernelName(dispatch_packet) : NULL; + data.submit.kernel_name = kernel_name; data.submit.queue = obj->queue_; data.submit.device_type = obj->agent_info_->dev_type; data.submit.device_id = obj->agent_info_->dev_index; @@ -167,16 +173,7 @@ class InterceptQueue { // Prepareing dispatch callback data uint64_t kernel_object = dispatch_packet->kernel_object; const amd_kernel_code_t* kernel_code = GetKernelCode(kernel_object); - - const uint16_t kernel_object_flag = *((uint64_t*)kernel_code + 1); - if (kernel_object_flag == 0) { - if (!util::HsaRsrcFactory::IsExecutableTracking()) { - EXC_ABORT(HSA_STATUS_ERROR, "Error: V3 code object detected - code objects tracking should be enabled\n"); - } - } - const char* kernel_name = (util::HsaRsrcFactory::IsExecutableTracking()) ? - util::HsaRsrcFactory::GetKernelName(kernel_object) : - GetKernelName(kernel_code->runtime_loader_kernel_symbol); + const char* kernel_name = QueryKernelName(kernel_object, kernel_code); rocprofiler_callback_data_t data = {obj->agent_info_->dev_id, obj->agent_info_->dev_index, @@ -314,6 +311,20 @@ class InterceptQueue { return funcname; } + static const char* QueryKernelName(uint64_t kernel_object, const amd_kernel_code_t* kernel_code) { + const uint16_t kernel_object_flag = *((uint64_t*)kernel_code + 1); + if (kernel_object_flag == 0) { + if (!util::HsaRsrcFactory::IsExecutableTracking()) { + EXC_ABORT(HSA_STATUS_ERROR, "Error: V3 code object detected - code objects tracking should be enabled\n"); + } + } + const char* kernel_name = (util::HsaRsrcFactory::IsExecutableTracking()) ? + util::HsaRsrcFactory::GetKernelName(kernel_object) : + GetKernelName(kernel_code->runtime_loader_kernel_symbol); + + return kernel_name; + } + // method to get an intercept queue object static InterceptQueue* GetObj(const hsa_queue_t* queue) { std::lock_guard lck(mutex_); diff --git a/projects/rocprofiler/src/core/prof_listener.h b/projects/rocprofiler/src/core/prof_listener.h deleted file mode 100644 index 47cd15cf96..0000000000 --- a/projects/rocprofiler/src/core/prof_listener.h +++ /dev/null @@ -1,183 +0,0 @@ -/****************************************************************************** -MIT License - -Copyright (c) 2018 ROCm Core Technology - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*******************************************************************************/ - -#ifndef _SRC_CORE_PROF_LISTENER_H -#define _SRC_CORE_PROF_LISTENER_H - -#include -#include -#include - -#include -#include -#include -#include - -#include "core/context.h" -#include "core/proxy_queue.h" -#include "core/tracker.h" -#include "core/types.h" -#include "inc/rocprofiler.h" -#include "util/hsa_rsrc_factory.h" - -namespace rocprofiler { - -class ProfListener { - public: - static void Callback(const void* in_packets, uint64_t count, uint64_t user_que_idx, void* data, - hsa_amd_queue_intercept_packet_writer writer) { - const packet_t* packets_arr = reinterpret_cast(in_packets); - InterceptQueue* obj = reinterpret_cast(data); - Queue* proxy = obj->proxy_; - - // Travers input packets - for (uint64_t j = 0; j < count; ++j) { - const packet_t* packet = &packets_arr[j]; - bool to_submit = true; - - // Checking for dispatch packet type - if ((GetHeaderType(packet) == HSA_PACKET_TYPE_KERNEL_DISPATCH) && (dispatch_callback_ != NULL)) { - const hsa_kernel_dispatch_packet_t* dispatch_packet = - reinterpret_cast(packet); - - // Adding kernel timing tracker - const rocprofiler_dispatch_record_t* record = NULL; - if (tracker_ != NULL) { - const auto* entry = tracker_->Add(obj->agent_info_->dev_id, dispatch_packet->completion_signal); - const_cast(dispatch_packet)->completion_signal = entry->signal; - record = entry->record; - } - - // Prepareing dispatch callback data - const char* kernel_name = GetKernelName(dispatch_packet); - rocprofiler_callback_data_t data = {obj->agent_info_->dev_id, - obj->agent_info_->dev_index, - obj->queue_, - user_que_idx, - dispatch_packet, - kernel_name, - record}; - - // Calling dispatch callback - rocprofiler_group_t group = {}; - hsa_status_t status = dispatch_callback_(&data, callback_data_, &group); - free(const_cast(kernel_name)); - // Injecting profiling start/stop packets - if ((status == HSA_STATUS_SUCCESS) && (group.context != NULL)) { - Context* context = reinterpret_cast(group.context); - const pkt_vector_t& start_vector = context->StartPackets(group.index); - const pkt_vector_t& stop_vector = context->StopPackets(group.index); - - pkt_vector_t packets = start_vector; - packets.insert(packets.end(), *packet); - packets.insert(packets.end(), stop_vector.begin(), stop_vector.end()); - if (writer != NULL) { - writer(&packets[0], packets.size()); - } else { - proxy->Submit(&packets[0], packets.size()); - } - to_submit = false; - } - } - - // Submitting the original packets if profiling was not enabled - if (to_submit) { - if (writer != NULL) { - writer(packet, 1); - } else { - proxy->Submit(packet, 1); - } - } - } - } - - static void SetProfCallbacks(rocprofiler_callback_t dispatch_callback, queue_callback_t destroy_callback, void* data) { - std::lock_guard lck(mutex_); - callback_data_ = data; - dispatch_callback_ = dispatch_callback; - destroy_callback_ = destroy_callback; - } - - void TrackerOn(bool on) { tracker_on_ = on; } - bool IsTrackerOn() { return tracker_on_; } - - private: - static hsa_packet_type_t GetHeaderType(const packet_t* packet) { - const packet_word_t* header = reinterpret_cast(packet); - return static_cast((*header >> HSA_PACKET_HEADER_TYPE) & header_type_mask); - } - - static const char* GetKernelName(const hsa_kernel_dispatch_packet_t* dispatch_packet) { - const amd_kernel_code_t* kernel_code = NULL; - hsa_status_t status = - util::HsaRsrcFactory::Instance().LoaderApi()->hsa_ven_amd_loader_query_host_address( - reinterpret_cast(dispatch_packet->kernel_object), - reinterpret_cast(&kernel_code)); - if (HSA_STATUS_SUCCESS != status) { - kernel_code = reinterpret_cast(dispatch_packet->kernel_object); - } - amd_runtime_loader_debug_info_t* dbg_info = reinterpret_cast( - kernel_code->runtime_loader_kernel_symbol); - const char* kernel_name = (dbg_info != NULL) ? dbg_info->kernel_name : NULL; - - // Kernel name is mangled name - // apply __cxa_demangle() to demangle it - const char* funcname = NULL; - if (kernel_name != NULL) { - size_t funcnamesize = 0; - int status; - const char* ret = abi::__cxa_demangle(kernel_name, NULL, &funcnamesize, &status); - funcname = (ret != 0) ? ret : strdup(kernel_name); - } - if (funcname == NULL) funcname = strdup(kernel_none_); - - return funcname; - } - - InterceptQueue(const hsa_agent_t& agent, hsa_queue_t* const queue, ProxyQueue* proxy) : - queue_(queue), - proxy_(proxy) - { - agent_info_ = util::HsaRsrcFactory::Instance().GetAgentInfo(agent); - } - ~InterceptQueue() { ProxyQueue::Destroy(proxy_); } - - static mutex_t mutex_; - static const packet_word_t header_type_mask = (1ul << HSA_PACKET_HEADER_WIDTH_TYPE) - 1; - static rocprofiler_callback_t dispatch_callback_; - static queue_callback_t destroy_callback_; - static void* callback_data_; - static obj_map_t* obj_map_; - static const char* kernel_none_; - static uint64_t timeout_; - static Tracker* tracker_; - static bool tracker_on_; - static bool in_constr_call_; - - const util::AgentInfo* agent_info_; -}; - -} // namespace rocprofiler - -#endif // _SRC_CORE_PROF_LISTENER_H diff --git a/projects/rocprofiler/src/core/rocprofiler.cpp b/projects/rocprofiler/src/core/rocprofiler.cpp index 14a370fcd5..3a45fdf6ed 100644 --- a/projects/rocprofiler/src/core/rocprofiler.cpp +++ b/projects/rocprofiler/src/core/rocprofiler.cpp @@ -54,6 +54,15 @@ THE SOFTWARE. } \ return status; +#define ONLOAD_TRACE(str) \ + if (getenv("ROCP_ONLOAD_TRACE")) do { \ + std::cout << "PID(" << GetPid() << "): PROF_LIB::" << __FUNCTION__ << " " << str << std::endl << std::flush; \ + } while(0); +#define ONLOAD_TRACE_BEG() ONLOAD_TRACE("begin") +#define ONLOAD_TRACE_END() ONLOAD_TRACE("end") + +static inline uint32_t GetPid() { return syscall(__NR_getpid); } + /////////////////////////////////////////////////////////////////////////////////////////////////// // Internal library methods // @@ -155,11 +164,12 @@ enum { DISPATCH_INTERCEPT_MODE = 0x1, CODE_OBJ_TRACKING_MODE = 0x2, MEMCOPY_INTERCEPT_MODE = 0x4, + HSA_INTERCEPT_MODE = 0x8, }; uint32_t LoadTool() { uint32_t intercept_mode = 0; const char* tool_lib = getenv("ROCP_TOOL_LIB"); - fprintf(stderr, "ROCProfiler: load tool library \"%s\"\n", tool_lib); fflush(stderr); + ONLOAD_TRACE("load tool library(" << tool_lib << ")"); if (tool_lib) { intercept_mode = DISPATCH_INTERCEPT_MODE; @@ -190,7 +200,6 @@ uint32_t LoadTool() { settings.trace_local = TraceProfile::IsLocal() ? 1: 0; settings.timeout = util::HsaRsrcFactory::GetTimeoutNs(); settings.timestamp_on = InterceptQueue::IsTrackerOn() ? 1 : 0; - settings.hsa_intercepting = 0; if (handler) handler(); else if (handler_prop) handler_prop(&settings); @@ -202,7 +211,7 @@ uint32_t LoadTool() { if (settings.intercept_mode != 0) intercept_mode = DISPATCH_INTERCEPT_MODE; if (settings.code_obj_tracking) intercept_mode |= CODE_OBJ_TRACKING_MODE; if (settings.memcopy_tracking) intercept_mode |= MEMCOPY_INTERCEPT_MODE; - HsaInterceptor::Enable(settings.hsa_intercepting != 0); + if (settings.hsa_intercepting) intercept_mode |= HSA_INTERCEPT_MODE; } return intercept_mode; @@ -415,7 +424,6 @@ extern "C" { // 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) { - fprintf(stderr, "rocprof OnLoad\n"); fflush(stderr); rocprofiler::SaveHsaApi(table); rocprofiler::ProxyQueue::InitFactory(); bool intercept_mode = false; @@ -462,6 +470,13 @@ PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t fa table->amd_ext_->hsa_amd_memory_async_copy_fn = rocprofiler::hsa_amd_memory_async_copy_interceptor; table->amd_ext_->hsa_amd_memory_async_copy_rect_fn = rocprofiler::hsa_amd_memory_async_copy_rect_interceptor; } + if (intercept_mode_mask & rocprofiler::HSA_INTERCEPT_MODE) { + if (intercept_mode_mask & rocprofiler::MEMCOPY_INTERCEPT_MODE) { + EXC_ABORT(HSA_STATUS_ERROR, "HSA_INTERCEPT and MEMCOPY_INTERCEPT conflict"); + } + rocprofiler::HsaInterceptor::Enable(true); + rocprofiler::HsaInterceptor::HsaIntercept(table); + } // HSA intercepting if (intercept_mode) { @@ -469,7 +484,6 @@ PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t fa rocprofiler::InterceptQueue::HsaIntercept(table); } else { rocprofiler::StandaloneIntercept(); - rocprofiler::HsaInterceptor::HsaIntercept(table); } return true; diff --git a/projects/rocprofiler/test/run.sh b/projects/rocprofiler/test/run.sh index ecc4aece87..3169f5dcca 100755 --- a/projects/rocprofiler/test/run.sh +++ b/projects/rocprofiler/test/run.sh @@ -97,9 +97,6 @@ export ROCP_TIMESTAMP_ON=1 # and SQTT trace files 'thread_trace.se.out' export ROCP_OUTPUT_DIR=./RESULTS -# enable HSA intercepting -export ROCP_HSA_INTERC=1 - if [ ! -e $ROCP_TOOL_LIB ] ; then export ROCP_TOOL_LIB=test/libtool.so fi @@ -140,6 +137,20 @@ export ROCP_OBJ_TRACKING=1 export ROCP_INPUT=input1.xml eval_test "libtool test, OpenCL sample" ./test/ocl/SimpleConvolution +# Memcopies tracking +unset ROCP_MCOPY_TRACKING +# enable HSA intercepting +export ROCP_HSA_INTERC=1 + +export ROCP_KITER=10 +export ROCP_DITER=10 +export ROCP_INPUT=input1.xml +eval_test "libtool test, counter sets" ./test/ctrl + +## OpenCL test +export ROCP_OBJ_TRACKING=1 +eval_test "libtool test, OpenCL sample" ./test/ocl/SimpleConvolution + #valgrind --leak-check=full $tbin #valgrind --tool=massif $tbin #ms_print massif.out. diff --git a/projects/rocprofiler/test/tool/tool.cpp b/projects/rocprofiler/test/tool/tool.cpp index 95cc38ddb9..463590858d 100644 --- a/projects/rocprofiler/test/tool/tool.cpp +++ b/projects/rocprofiler/test/tool/tool.cpp @@ -964,6 +964,7 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) check_env_var("ROCP_MCOPY_TRACKING", settings->memcopy_tracking); // Set HSA intercepting check_env_var("ROCP_HSA_INTERC", settings->hsa_intercepting); + if (settings->hsa_intercepting) rocprofiler_set_hsa_callbacks(hsa_callbacks, (void*)14); is_trace_local = settings->trace_local;