diff --git a/inc/rocprofiler.h b/inc/rocprofiler.h index a0d186526f..a1473d18a2 100644 --- a/inc/rocprofiler.h +++ b/inc/rocprofiler.h @@ -376,13 +376,25 @@ hsa_status_t rocprofiler_query_info( hsa_status_t (*callback)(const rocprofiler_info_data_t info, void *data), // callback void *data); // [in/out] data passed to callback -// Creates a profiled queue. All dispatches on this queue will be profiled +// Create a profiled queue. All dispatches on this queue will be profiled hsa_status_t rocprofiler_queue_create_profiled( hsa_agent_t agent_handle,uint32_t size, hsa_queue_type32_t type, void (*callback)(hsa_status_t status, hsa_queue_t* source, void* data), void* data, uint32_t private_segment_size, uint32_t group_segment_size, hsa_queue_t** queue); +// Convert profiler time +typedef enum { + ROCPROFILER_TIME_ID_CLOCK_REALTIME = 0, + ROCPROFILER_TIME_ID_CLOCK_MONOTONIC = 1, +} rocprofiler_time_id_t; + +// Return time for a given time ID and profiling timetsamp value +hsa_status_t rocprofiler_get_time( + rocprofiler_time_id_t time_id, // identifier of the particular time to convert the timesatmp + uint64_t value, // profiling timestamp value + uint64_t* time); // returned time + //////////////////////////////////////////////////////////////////////////////// // Profiling pool // diff --git a/src/core/rocprofiler.cpp b/src/core/rocprofiler.cpp index 61fd4619ae..d553db36e1 100644 --- a/src/core/rocprofiler.cpp +++ b/src/core/rocprofiler.cpp @@ -843,4 +843,13 @@ PUBLIC_API hsa_status_t rocprofiler_queue_create_profiled( return rocprofiler::InterceptQueue::QueueCreateTracked(agent, size, type, callback, data, private_segment_size, group_segment_size, queue); } +// Return time for a given time ID and profiling timetsamp value +hsa_status_t rocprofiler_get_time( + rocprofiler_time_id_t time_id, + uint64_t value, + uint64_t* time) +{ + return rocprofiler::util::HsaRsrcFactory::Instance().GetTime(time_id, value, time); +} + } // extern "C" diff --git a/src/util/hsa_rsrc_factory.cpp b/src/util/hsa_rsrc_factory.cpp index 65f94357ca..674aa94b9f 100644 --- a/src/util/hsa_rsrc_factory.cpp +++ b/src/util/hsa_rsrc_factory.cpp @@ -150,6 +150,19 @@ HsaRsrcFactory::HsaRsrcFactory(bool initialize_hsa) : initialize_hsa_(initialize CHECK_STATUS("HSA timer allocation failed", (timer_ == NULL) ? HSA_STATUS_ERROR : HSA_STATUS_SUCCESS); + // Time correlation + const uint32_t corr_iters = 1000; + CorrelateTime(HsaTimer::TIME_ID_CLOCK_REALTIME, corr_iters); + CorrelateTime(HsaTimer::TIME_ID_CLOCK_MONOTONIC, corr_iters); +#if 0 + printf("ROCProfiler time CLOCK_REALTIME: shift(0x%016lx) error(0x%lx)\n", + time_shift_[HsaTimer::TIME_ID_CLOCK_REALTIME], + time_error_[HsaTimer::TIME_ID_CLOCK_REALTIME]); + printf("ROCProfiler time CLOCK_MONOTONIC: shift(0x%016lx) error(0x%lx)\n", + time_shift_[HsaTimer::TIME_ID_CLOCK_MONOTONIC], + time_error_[HsaTimer::TIME_ID_CLOCK_MONOTONIC]); +#endif + // System timeout timeout_ = (timeout_ns_ == HsaTimer::TIMESTAMP_MAX) ? timeout_ns_ : timer_->ns_to_sysclock(timeout_ns_); } diff --git a/src/util/hsa_rsrc_factory.h b/src/util/hsa_rsrc_factory.h index bf7f5fcfde..0362bc2c94 100644 --- a/src/util/hsa_rsrc_factory.h +++ b/src/util/hsa_rsrc_factory.h @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -177,6 +178,12 @@ class HsaTimer { static const timestamp_t TIMESTAMP_MAX = UINT64_MAX; typedef long double freq_t; + enum time_id_t { + TIME_ID_CLOCK_REALTIME = 0, + TIME_ID_CLOCK_MONOTONIC = 1, + TIME_ID_NUMBER + }; + HsaTimer(const hsa_pfn_t* hsa_api) : hsa_api_(hsa_api) { timestamp_t sysclock_hz = 0; hsa_status_t status = hsa_api_->hsa_system_get_info(HSA_SYSTEM_INFO_TIMESTAMP_FREQUENCY, &sysclock_hz); @@ -192,6 +199,11 @@ class HsaTimer { return timestamp_t((freq_t)time / sysclock_factor_); } + // Method for timespec/ns conversion + timestamp_t timespec_to_ns(const timespec& time) const { + return ((timestamp_t)time.tv_sec * 1000000000) + time.tv_nsec; + } + // Return timestamp in 'ns' timestamp_t timestamp_ns() const { timestamp_t sysclock; @@ -200,6 +212,54 @@ class HsaTimer { return sysclock_to_ns(sysclock); } + // Return time in 'ns' + timestamp_t clocktime_ns(clockid_t clock_id) const { + timespec time; + clock_gettime(clock_id, &time); + return timespec_to_ns(time); + } + + // Return pair of correlated values of profiling timestamp and time with + // correlation error for a given time ID and number of iterations + void correlated_pair_ns(time_id_t time_id, uint32_t iters, + timestamp_t* timestamp_v, timestamp_t* time_v, timestamp_t* error_v) { + clockid_t clock_id = 0; + switch (clock_id) { + case TIME_ID_CLOCK_REALTIME: + clock_id = CLOCK_REALTIME; + break; + case TIME_ID_CLOCK_MONOTONIC: + clock_id = CLOCK_MONOTONIC; + break; + default: + CHECK_STATUS("internal error: invalid time_id", HSA_STATUS_ERROR); + } + + std::vector ts_vec(iters); + std::vector tm_vec(iters); + const uint32_t steps = iters - 1; + + for (uint32_t i = 0; i < iters; ++i) { + hsa_api_->hsa_system_get_info(HSA_SYSTEM_INFO_TIMESTAMP, &ts_vec[i]); + clock_gettime(clock_id, &tm_vec[i]); + } + + const timestamp_t ts_base = sysclock_to_ns(ts_vec.front()); + const timestamp_t tm_base = timespec_to_ns(tm_vec.front()); + const timestamp_t error = (ts_vec.back() - ts_vec.front()) / (2 * steps); + + timestamp_t ts_accum = 0; + timestamp_t tm_accum = 0; + for (uint32_t i = 0; i < iters; ++i) { + ts_accum += (ts_vec[i] - ts_base); + tm_accum += (timespec_to_ns(tm_vec[i]) - tm_base); + } + + *timestamp_v = (ts_accum / iters) + ts_base + error; + *time_v = (tm_accum / iters) + tm_base; + *error_v = error; + } + private: // Timestamp frequency factor freq_t sysclock_factor_; @@ -359,6 +419,21 @@ class HsaRsrcFactory { if (instance_ != NULL) Instance().timeout_ = Instance().timer_->ns_to_sysclock(time); } + void CorrelateTime(HsaTimer::time_id_t time_id, uint32_t iters) { + timestamp_t timestamp_v = 0; + timestamp_t time_v = 0; + timestamp_t error_v = 0; + timer_->correlated_pair_ns(time_id, iters, ×tamp_v, &time_v, &error_v); + time_shift_[time_id] = time_v - timestamp_v; + time_error_[time_id] = error_v; + } + + hsa_status_t GetTime(uint32_t time_id, uint64_t value, uint64_t* time) { + if (time_id >= HsaTimer::TIME_ID_NUMBER) return HSA_STATUS_ERROR; + *time = value + time_shift_[time_id]; + return HSA_STATUS_SUCCESS; + } + private: // System agents iterating callback static hsa_status_t GetHsaAgentsCallback(hsa_agent_t agent, void* data); @@ -423,6 +498,10 @@ class HsaRsrcFactory { // HSA timer HsaTimer* timer_; + // Time shift array to support time conversion + timestamp_t time_shift_[HsaTimer::TIME_ID_NUMBER]; + timestamp_t time_error_[HsaTimer::TIME_ID_NUMBER]; + // CPU/kern-arg memory pools hsa_amd_memory_pool_t *cpu_pool_; hsa_amd_memory_pool_t *kern_arg_pool_;