Fix profiling calculation for CPU profiling path.

-There was a precision problem with timestamp calculation, all math was using
integers which are not very precise in overflow scenarios
-Change the logic to use doubles and cast back to uint64_t at the end.

Change-Id: Ia08d504a90a43df7330f398af966535ed944650d
This commit is contained in:
Mrozek, Michal
2018-02-19 15:04:03 +01:00
committed by sys_ocldev
parent 063e9623ba
commit ca33e029b7
4 changed files with 30 additions and 5 deletions

View File

@@ -85,11 +85,9 @@ bool OSTimeWin::getCpuGpuTime(TimeStampData *pGpuCpuTime) {
bool OSTimeWin::getCpuTime(uint64_t *timeStamp) {
uint64_t time;
uint64_t frequency;
QueryPerformanceCounter((LARGE_INTEGER *)&time);
QueryPerformanceFrequency((LARGE_INTEGER *)&frequency);
this->QueryPerfomanceCounterFnc((LARGE_INTEGER *)&time);
*timeStamp = time * NSEC_PER_SEC / frequency;
*timeStamp = static_cast<uint64_t>((static_cast<double>(time) * NSEC_PER_SEC / frequency.QuadPart));
return true;
};
@@ -126,7 +124,7 @@ double OSTimeWin::getDynamicDeviceTimerResolution(HardwareInfo const &hwInfo) co
uint64_t OSTimeWin::getCpuRawTimestamp() {
LARGE_INTEGER cpuRawTimestamp = {};
QueryPerformanceCounter(&cpuRawTimestamp);
this->QueryPerfomanceCounterFnc(&cpuRawTimestamp);
return cpuRawTimestamp.QuadPart;
}
} // namespace OCLRT

View File

@@ -42,6 +42,7 @@ class OSTimeWin : public OSTime {
Wddm *wddm;
LARGE_INTEGER frequency;
OSTimeWin() {}
decltype(&QueryPerformanceCounter) QueryPerfomanceCounterFnc = QueryPerformanceCounter;
};
typedef enum GTDI_ESCAPE_FUNCTION_ENUM {

View File

@@ -27,6 +27,11 @@ namespace OCLRT {
class MockOSTimeWin : public OSTimeWin {
public:
MockOSTimeWin(OSInterface *osInterface) : OSTimeWin(osInterface){};
void overrideQueryPerformanceCounterFunction(decltype(&QueryPerformanceCounter) function) {
this->QueryPerfomanceCounterFnc = function;
}
void setFrequency(LARGE_INTEGER frequency) {
this->frequency = frequency;
}

View File

@@ -25,6 +25,15 @@
#include <memory>
using namespace OCLRT;
LARGE_INTEGER valueToSet = {0};
BOOL WINAPI QueryPerformanceCounterMock(
_Out_ LARGE_INTEGER *lpPerformanceCount) {
*lpPerformanceCount = valueToSet;
return true;
};
struct OSTimeWinTest : public ::testing::Test {
public:
virtual void SetUp() override {
@@ -56,3 +65,15 @@ TEST_F(OSTimeWinTest, givenOsTimeWinWhenGetCpuRawTimestampIsCalledThenReturnsNon
auto retVal = osTime->getCpuRawTimestamp();
EXPECT_NE(0ull, retVal);
}
TEST_F(OSTimeWinTest, givenHighValueOfCpuTimestampWhenItIsObtainedThenItHasProperValue) {
osTime->overrideQueryPerformanceCounterFunction(QueryPerformanceCounterMock);
LARGE_INTEGER frequency = {0};
frequency.QuadPart = 190457;
osTime->setFrequency(frequency);
valueToSet.QuadPart = 700894514854;
uint64_t timeStamp = 0;
uint64_t expectedTimestamp = static_cast<uint64_t>((static_cast<double>(valueToSet.QuadPart) * static_cast<double>(NSEC_PER_SEC) / static_cast<double>(frequency.QuadPart)));
osTime->getCpuTime(&timeStamp);
EXPECT_EQ(expectedTimestamp, timeStamp);
}