|
|
#include "../../include/timer.h" |
|
|
|
|
|
|
|
|
#ifndef HIPRT_CB |
|
|
#define HIPRT_CB |
|
|
#endif |
|
|
|
|
|
|
|
|
class KernelTimer; |
|
|
|
|
|
|
|
|
static void HIPRT_CB eventCallback(hipStream_t stream, hipError_t status, void* userData) { |
|
|
if (status != hipSuccess) return; |
|
|
|
|
|
KernelTimer* timer = static_cast<KernelTimer*>(userData); |
|
|
float elapsed_time; |
|
|
|
|
|
|
|
|
HOST_TYPE(Event_t) start_event = timer->get_start_event(); |
|
|
HOST_TYPE(Event_t) stop_event = timer->get_stop_event(); |
|
|
|
|
|
LIB_CALL(HOST_TYPE(EventElapsedTime)(&elapsed_time, start_event, stop_event)); |
|
|
|
|
|
size_t calc_ops = timer->get_calc_ops(); |
|
|
double flops = static_cast<double>(calc_ops); |
|
|
double gflops_val = (flops / (elapsed_time * 1e-3)) / 1e9; |
|
|
|
|
|
|
|
|
float* time_ptr = timer->get_time_ptr(); |
|
|
float* gflops_ptr = timer->get_gflops_ptr(); |
|
|
|
|
|
if (time_ptr != nullptr) { |
|
|
*time_ptr = elapsed_time; |
|
|
} |
|
|
if (gflops_ptr != nullptr) { |
|
|
*gflops_ptr = static_cast<float>(gflops_val); |
|
|
} |
|
|
|
|
|
|
|
|
timer->execute_callback(elapsed_time); |
|
|
timer->set_callback_executed(true); |
|
|
} |
|
|
|
|
|
KernelTimer::KernelTimer(size_t calc_ops, float *time, float *gflops) |
|
|
: calc_ops(calc_ops), time_ptr(time), gflops_ptr(gflops), user_data(nullptr), |
|
|
callback(nullptr), callback_executed(false) { |
|
|
LIB_CALL(HOST_TYPE(EventCreate)(&start)); |
|
|
LIB_CALL(HOST_TYPE(EventCreate)(&stop)); |
|
|
} |
|
|
|
|
|
void KernelTimer::start_timer(hipStream_t stream) { |
|
|
LIB_CALL(HOST_TYPE(EventRecord)(start, stream)); |
|
|
callback_executed = false; |
|
|
} |
|
|
|
|
|
void KernelTimer::stop_timer(hipStream_t stream) { |
|
|
LIB_CALL(HOST_TYPE(EventRecord)(stop, stream)); |
|
|
|
|
|
LIB_CALL(hipStreamAddCallback(stream, eventCallback, this, 0)); |
|
|
} |
|
|
|
|
|
void KernelTimer::set_callback(TimerCompletionCallback cb, void* data) { |
|
|
callback = cb; |
|
|
user_data = data; |
|
|
} |
|
|
|
|
|
void KernelTimer::execute_callback(float elapsed_time) { |
|
|
if (callback && !callback_executed) { |
|
|
callback(elapsed_time, calc_ops, time_ptr, gflops_ptr, user_data); |
|
|
} |
|
|
} |
|
|
|
|
|
void KernelTimer::synchronize() { |
|
|
|
|
|
if (!callback_executed) { |
|
|
LIB_CALL(HOST_TYPE(EventSynchronize)(stop)); |
|
|
float elapsed_time; |
|
|
LIB_CALL(HOST_TYPE(EventElapsedTime)(&elapsed_time, start, stop)); |
|
|
|
|
|
double flops = static_cast<double>(calc_ops); |
|
|
double gflops_val = (flops / (elapsed_time * 1e-3)) / 1e9; |
|
|
|
|
|
|
|
|
if (time_ptr != nullptr) { |
|
|
*time_ptr = elapsed_time; |
|
|
} |
|
|
if (gflops_ptr != nullptr) { |
|
|
*gflops_ptr = static_cast<float>(gflops_val); |
|
|
} |
|
|
|
|
|
|
|
|
if (callback) { |
|
|
callback(elapsed_time, calc_ops, time_ptr, gflops_ptr, user_data); |
|
|
} |
|
|
callback_executed = true; |
|
|
} |
|
|
} |
|
|
|
|
|
KernelTimer::~KernelTimer() { |
|
|
|
|
|
synchronize(); |
|
|
LIB_CALL(HOST_TYPE(EventDestroy)(start)); |
|
|
LIB_CALL(HOST_TYPE(EventDestroy)(stop)); |
|
|
} |