1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*
* Copyright (C) 2020-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/os_time.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/hw_info.h"
#include <mutex>
namespace NEO {
double OSTime::getDeviceTimerResolution(HardwareInfo const &hwInfo) {
return hwInfo.capabilityTable.defaultProfilingTimerResolution;
};
bool DeviceTime::getGpuCpuTimeImpl(TimeStampData *pGpuCpuTime, OSTime *osTime) {
pGpuCpuTime->cpuTimeinNS = 0;
pGpuCpuTime->gpuTimeStamp = 0;
return true;
}
double DeviceTime::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) const {
return OSTime::getDeviceTimerResolution(hwInfo);
}
uint64_t DeviceTime::getDynamicDeviceTimerClock(HardwareInfo const &hwInfo) const {
return static_cast<uint64_t>(1000000000.0 / OSTime::getDeviceTimerResolution(hwInfo));
}
void DeviceTime::setDeviceTimerResolution(HardwareInfo const &hwInfo) {
deviceTimerResolution = getDynamicDeviceTimerResolution(hwInfo);
if (debugManager.flags.OverrideProfilingTimerResolution.get() != -1) {
deviceTimerResolution = static_cast<double>(debugManager.flags.OverrideProfilingTimerResolution.get());
}
}
bool DeviceTime::isTimestampsRefreshEnabled() const {
bool timestampsRefreshEnabled = true;
if (debugManager.flags.EnableReusingGpuTimestamps.get() != -1) {
timestampsRefreshEnabled = debugManager.flags.EnableReusingGpuTimestamps.get();
}
return timestampsRefreshEnabled;
}
/**
* @brief If this method is called within interval, GPU timestamp
* will be calculated based on CPU timestamp and previous GPU ticks
* to reduce amount of internal KMD calls. Interval is selected
* adaptively, based on misalignment between calculated ticks and actual ticks.
*
* @return returns false if internal call to KMD failed. True otherwise.
*/
bool DeviceTime::getGpuCpuTimestamps(TimeStampData *timeStamp, OSTime *osTime, bool forceKmdCall) {
uint64_t cpuTimeinNS;
osTime->getCpuTime(&cpuTimeinNS);
auto cpuTimeDiffInNS = cpuTimeinNS - fetchedTimestamps.cpuTimeinNS;
if (forceKmdCall || cpuTimeDiffInNS >= timestampRefreshTimeoutNS) {
refreshTimestamps = true;
}
bool reusingTimestampsEnabled = isTimestampsRefreshEnabled();
if (!reusingTimestampsEnabled || refreshTimestamps) {
if (!getGpuCpuTimeImpl(timeStamp, osTime)) {
return false;
}
if (!reusingTimestampsEnabled) {
return true;
}
if (initialGpuTimeStamp) {
UNRECOVERABLE_IF(deviceTimerResolution == 0);
auto calculatedTimestamp = fetchedTimestamps.gpuTimeStamp + static_cast<uint64_t>(cpuTimeDiffInNS / deviceTimerResolution);
auto diff = abs(static_cast<int64_t>(timeStamp->gpuTimeStamp - calculatedTimestamp));
auto elapsedTicks = timeStamp->gpuTimeStamp - fetchedTimestamps.gpuTimeStamp;
int64_t adaptValue = static_cast<int64_t>(diff * deviceTimerResolution);
adaptValue = std::min(adaptValue, static_cast<int64_t>(timestampRefreshMinTimeoutNS));
if (diff * 1.0f / elapsedTicks > 0.05) {
adaptValue = adaptValue * (-1);
}
timestampRefreshTimeoutNS += adaptValue;
timestampRefreshTimeoutNS = std::max(timestampRefreshMinTimeoutNS, std::min(timestampRefreshMaxTimeoutNS, timestampRefreshTimeoutNS));
}
fetchedTimestamps = *timeStamp;
refreshTimestamps = false;
} else {
timeStamp->cpuTimeinNS = cpuTimeinNS;
UNRECOVERABLE_IF(deviceTimerResolution == 0);
timeStamp->gpuTimeStamp = fetchedTimestamps.gpuTimeStamp + static_cast<uint64_t>(cpuTimeDiffInNS / deviceTimerResolution);
}
return true;
}
bool DeviceTime::getGpuCpuTime(TimeStampData *pGpuCpuTime, OSTime *osTime, bool forceKmdCall) {
if (!getGpuCpuTimestamps(pGpuCpuTime, osTime, forceKmdCall)) {
return false;
}
auto maxGpuTimeStampValue = osTime->getMaxGpuTimeStamp();
static std::mutex gpuTimeStampOverflowCounterMutex;
std::lock_guard<std::mutex> lock(gpuTimeStampOverflowCounterMutex);
pGpuCpuTime->gpuTimeStamp &= (maxGpuTimeStampValue - 1);
if (!initialGpuTimeStamp) {
initialGpuTimeStamp = pGpuCpuTime->gpuTimeStamp;
waitingForGpuTimeStampOverflow = true;
} else {
if (waitingForGpuTimeStampOverflow && pGpuCpuTime->gpuTimeStamp < *initialGpuTimeStamp) {
gpuTimeStampOverflowCounter++;
waitingForGpuTimeStampOverflow = false;
}
if (!waitingForGpuTimeStampOverflow && pGpuCpuTime->gpuTimeStamp > *initialGpuTimeStamp) {
waitingForGpuTimeStampOverflow = true;
}
pGpuCpuTime->gpuTimeStamp += gpuTimeStampOverflowCounter * maxGpuTimeStampValue;
}
return true;
}
bool OSTime::getCpuTime(uint64_t *timeStamp) {
*timeStamp = 0;
return true;
}
double OSTime::getHostTimerResolution() const {
return 0;
}
uint64_t OSTime::getCpuRawTimestamp() {
return 0;
}
OSTime::OSTime(std::unique_ptr<DeviceTime> deviceTime) {
this->deviceTime = std::move(deviceTime);
}
} // namespace NEO
|