2015-10-21 5 views
-1

В C# Я использую класс Stopwatch. Я могу получить тики и миллисекунды без проблем.Перемещение с C# на C++, QueryPerformanceCounter против часов создает запутывающие результаты

Теперь, когда я тестирую код во время обучения C++, я пытаюсь получить измерения, но Я не знаю, где результаты совпадают с эквивалентом решения секундомера C#. Я пытался искать, но информация слишком широка, и я не мог найти абсолютное решение.

double PCFreq = 0.0; 
__int64 CounterStart = 0; 
void StartCounter() 
{ 
    LARGE_INTEGER li; 
    if(!QueryPerformanceFrequency(&li)) 
    std::cout << "QueryPerformanceFrequency failed!\n"; 
    PCFreq = double(li.QuadPart)/1000.0; 
    QueryPerformanceCounter(&li); 
    CounterStart = li.QuadPart; 
} 

double GetCounter() 
{ 
    LARGE_INTEGER li; 
    QueryPerformanceCounter(&li); 
    return double(li.QuadPart-CounterStart)/PCFreq; 
} 

Как это дает мне два разных результата, я склонен верить часам. :)

start = StartCounter() 
//some function or for loop 
end = GetCounter() 
marginPc = end - start; 

start = clock(); 
// ...same 
end= clock(); 
marginClck = end - start; 

std::cout<< "Res Pc: " << marginPc << "\r\nRes Clck: " marginClck<< std::endl; 

С версией часов я пытался как unsigned int и double, но результаты все еще были разные.

Каков правильный метод, эквивалентный секундомеру C#?

+3

Заканчивать [C++ кросс-платформенный высокое разрешение таймер] (http://stackoverflow.com/questions/1487695/c-cross-platform-high- разрешение-таймер? lq = 1) –

+2

Вы не должны ожидать, что «некоторая функция или цикл» займет такое же количество времени, если выполняется дважды (например, могут быть кеширование побочных эффектов, что ускоряет второй запуск); поместите оба таймера вокруг него и запустите его один раз, а затем сравните измерения часов. Почему бы вам не пожаловаться на то, что они отличаются друг от друга, не давая никаких измерений, с помощью которых мы можем определить, насколько это важно? Различия в том, сколько микросекунд? И 'QueryPerformanceFrequency' исторически был ненадежной кучей дерьма. Если у вас есть поддержка RDTSCP, вы можете использовать ее напрямую .... –

+1

@TonyD благодарит за комментарий: «Возможно, кеширование побочных эффектов делает второй запуск быстрее», как вы могли бы узнать, когда это возможно/невозможно ? кстати, это была не разница в MS, цифры были совершенно неправильными –

ответ

1

clock() дает вам количество миллисекунд с момента запуска программы. Например, следующая программа напечатает число близко к 500:

int main() 
{ 
    Sleep(500); 
    cout << clock() << endl; 

    /* 
    POSIX version: 
    std::cout << clock() * 1000.0/CLOCKS_PER_SEC << std::endl; 
    CLOCKS_PER_SEC is 1000 in Windows 
    */ 

    return 0; 
} 

QueryPerformanceCounter является своего рода похожи на GetTickCount64, оно основано на времени, когда компьютер начал. Когда вы выполняете вычитание типа Stop-Watch, результаты очень близки. QueryPerformanceCounter более точный. chrono метод от @ ссылка BoPersson также базируется на QueryPerformanceCounter.

MSDN рекомендует использовать QueryPerformanceCounter (QPC) для высоких марок разрешение:
Acquiring high-resolution time stamps

Та же функция QPC используется в управляемом коде:

Для управляемого кода, то System.Diagnostics.Stopwatch класс использует QPC как его точное временное основание

Эта функция должна иметь разумную точность:

long long getmicroseconds() 
{ 
    LARGE_INTEGER fq, t; 
    QueryPerformanceFrequency(&fq); 
    QueryPerformanceCounter(&t); 
    return 1000000 * t.QuadPart/fq.QuadPart; 
} 

Компьютерные часы обычно точные до +/- 1 секунду в день.

Из выше ссылке:

Duration   Uncertainty 
1 microsecond  ± 10 picoseconds (10-12) 
1 millisecond  ± 10 nanoseconds (10-9) 
1 second   ± 10 microseconds 
1 hour   ± 60 microseconds 
1 day    ± 0.86 seconds 
1 week   ± 6.08 seconds 

Чтобы упростить другие функции, вы можете избежать double результатов.QuadPart является long long, так что используйте, что на протяжении функций:

long long PCFreq = 0; 
long long CounterStart = 0; 
void StartCounter() 
{ 
    LARGE_INTEGER li; 
    QueryPerformanceFrequency(&li); 
    PCFreq = li.QuadPart; 
    QueryPerformanceCounter(&li); 
    CounterStart = li.QuadPart; 
} 

long long GetCounter() 
{ 
    if (PCFreq < 1) return 0; 
    LARGE_INTEGER li; 
    QueryPerformanceCounter(&li); 

    //for milliseconds: 1,000 
    return 1000 * (li.QuadPart - CounterStart)/PCFreq; 

    //for microseconds: 1,000,000 
    //return 1000000 * (li.QuadPart - CounterStart)/PCFreq; 
} 
+0

Я только учился, я думаю, что никто не заметил этого, что я просто копировал эту реализацию после использования 'clock()', что привело меня к поиску более ясный пример, что код был отправлен где-то, я почти уверен, что это был ответ здесь, в SO, в любом случае я благодарю вас за то, что я внес свой вклад в мою проблему с вашей стратегией для точки оповещения, и я просто надеюсь, что на этот раз я получу рабочий код для тестирования с благодарностью Barmak! –

+0

Я не уверен в вашем вопросе. Результат от 'clock' и' QueryPerformanceFrequency' должен быть одинаковым для секундомера. Есть некоторые отличия. См. Обновленный ответ. –

+0

в обмен на вашу попытку confus: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=7&cad=rja&uact=8&ved=0CEcQFjAGahUKEwjyrc7vpdTIAhXD7RQKHQf_BjQ&url=http%3A%2F%2Fwww.cs .sfu.ca% 2F ~ ashriram% 2Fcourses% 2F2012% 2FCS479% 2Fproject% 2FTSP% 2Fhrtime.h & USG = AFQjCNHELcgs7LwAR-XWp4deVvvBDRpYBg & Sig2 = AcUtksuaPn73okl5Nn_rzg искать мс, если DEFS причина я заблудилась ... увидеть, если они говорят, что какой-либо иной –

1

Ваша ошибка. У вас есть StartCounter возвращение CounterStart = li.QuadPart;

Но GetCounterdouble(li.QuadPart-CounterStart)/PCFreq.

I.e. один делится на PCFreq, а другой нет. Недействительно, чтобы затем вычесть один из другого.

+0

спасибо ben, то же самое касается u, см. @ Barmak Shemirani, спасибо большое спасибо –

Смежные вопросы