Войти
ПрограммированиеФорумОбщее

QueryPerformanceCounter и многоядерность (2 стр)

Страницы: 1 2 3 48 Следующая »
#15
14:27, 7 окт. 2010

QueryPerformanceCounter не всегда просто выдает счетчик тиков процессора.
Чтобы проблем не было, надо просто устанавливать драйвера материнской карточки, QueryPerformanceCounter будет единым, сколько бы процессоров у вас не было.
Хотя, в msdn написано предупреждение, чтобы не пользовались QueryPerformanceCounter в условиях множества процессоров. Подозреваю, что это предупреждение - либо перестраховка, либо устарело.

Есть еще эффект, про который не все знают. PerformanceCounter имеет право тикать неравномерно и это реально бывает не так уж и редко. На материнских платах с чипсетом от via ситуация встречается постоянно. Не все такты материнская плата может пропускать до процессора, соответственно счетчик их не учитывает.


#16
14:27, 7 окт. 2010

Executor
> 5 мс, куда к чёрту...
это точность, а разрешающая способность у него миллисекундная - нужно выше?
к тому же, точность легко повышается до миллисекунды через timeBeginPeriod, что сто лет уже используется

а с QueryPerformanceCounter в отдельном потоке и со Sleep'ом точность будет те же 10-15мс, как заметил Andru...

#17
14:42, 7 окт. 2010

arabesc
> а с QueryPerformanceCounter в отдельном потоке и со Sleep'ом точность будет те
> же 10-15мс, как заметил Andru...

Можно и без Sleep спокойно.

Zab
> Чтобы проблем не было, надо просто устанавливать драйвера материнской карточки,
> QueryPerformanceCounter будет единым, сколько бы процессоров у вас не было.

Именно так и предложила мне игра Global Agenda, которая почему-то вываливалась с
эксепшеном когда из таймера получала отрицательное значение и предлагала
поставить драйвера, драйвера я поставил но ничего не поменялось, вот и думай.

#18
14:43, 7 окт. 2010

Zab
> Хотя, в msdn написано предупреждение, чтобы не пользовались
> QueryPerformanceCounter в условиях множества процессоров. Подозреваю, что это
> предупреждение - либо перестраховка, либо устарело.

Если он может возникнуть хотя бы у одного пользователя из миллиона, почему бы его не устранить написав код более правильным?

> Есть еще эффект, про который не все знают. PerformanceCounter имеет право
> тикать неравномерно и это реально бывает не так уж и редко. На материнских
> платах с чипсетом от via ситуация встречается постоянно. Не все такты
> материнская плата может пропускать до процессора, соответственно счетчик их не
> учитывает.

У меня на ноуте как раз via, проблем не испытывал... Раскрой тему шире...

arabesc
"This function affects a global Windows setting."
Поэтому в топку...

#19
14:46, 7 окт. 2010

>> к тому же, точность легко повышается до миллисекунды через timeBeginPeriod, что сто лет уже используется

Хмм, надо будет таки поковырять это дело, а то нехорошо как-то - под никсами использую нормальный GetTimeOfDay и все ок, а под вендой галиматью с кучей проблем... :)

#20
14:50, 7 окт. 2010

KpeHDeJIb
>> Можно и без Sleep спокойно.

С event'тами и wait'ами играться? :)

#21
14:54, 7 окт. 2010

Чем эвент в данном случае плох?

#22
15:04, 7 окт. 2010

Executer
>> Чем эвент в данном случае плох?

Да я просто спросил. Просто как-то не занимался вопросом "какое время может тратится для реакции WaitForSingleObject на SetEvent", но так понимаю - "мгновенно"?

#23
15:07, 7 окт. 2010

Executor
> У меня так... Разница в скорости 30-35%...
Это у тебя с кодом косяки, а не с методом. Точнее это особенность операционки. Если у тебя один поток, то нет особой разницы, будет он к ядру привязан или нет. Коррективы вносит ОС. Правильное решение - юзать все возможные ядра, и на каждом свой таймер.

#24
15:19, 7 окт. 2010

Executor

  SetProcessAffinityMask(GetCurrentProcess(), 1);
  QueryPerformanceCounter(count);
Это сработать не должно, по идее. SetProcessAffinityMask не прерывает текущий квант времени.

Возможно, решит проблему добавление sleep:

  SetProcessAffinityMask(GetCurrentProcess(), 1);
  sleep(0);
  QueryPerformanceCounter(count);

Но что мы замерим? sleep(0) может работать дольше одной десятой доли секунды.

#25
15:34, 7 окт. 2010

Executor
Не парься с этим.
Это аппаратный таймер производительности и никак не связан с количеством выполнения тактов. Для многядерных систем он один единственный, а для многопроцессорных системы есть Remark (c сайта http://msdn.microsoft.com/en-us/library/ms644904(VS.85).aspx):
On a multiprocessor computer, it should not matter which processor is called. However, you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL). To specify processor affinity for a thread, use the SetThreadAffinityMask function.

#26
16:00, 7 окт. 2010

Мизраэль
> Это у тебя с кодом косяки, а не с методом. Точнее это особенность операционки.

Так косяки кода или особенность операционки? :)

> Если у тебя один поток, то нет особой разницы, будет он к ядру привязан или нет.

Разница огромная, уже писал всё это десять раз... Разговор не о том...

asvp
> On a multiprocessor computer, it should not matter which processor is called.
> However, you can get different results on different processors due to bugs in
> the basic input/output system (BIOS) or the hardware abstraction layer (HAL).
> To specify processor affinity for a thread, use the SetThreadAffinityMask
> function.

Дык про это и разговор...

#27
19:15, 7 окт. 2010

хм , странно что я этого тут не прочёл (мож плохо смотрел)...  потому напишу сам:

Дело в том, что QueryPerformanceCounter возвращает счётчик выполнения, который ЗАВИСИТ  от многих факторов и следовательно может "плавать"  и плавает.

  Чтобы получить точное значение её обязательно надо использовать в паре с QueryPerformanceFrequency.

   /** \brief Получить текуще значение времени */
   static float Current() {
   LARGE_INTEGER tm, freq;   QueryPerformanceCounter(&tm); QueryPerformanceFrequency(&freq);
    return   (   ( (float)tm.QuadPart ) / ( (float)freq.QuadPart )   );
   };

пример:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

static float Current() {
  LARGE_INTEGER tm, freq;   QueryPerformanceCounter(&tm); QueryPerformanceFrequency(&freq);
  return   (   ( (float)tm.QuadPart ) / ( (float)freq.QuadPart )   );
};

int _tmain(int argc, _TCHAR* argv[])
{
  float fcurr , felaps ;
  while(true) {
    fcurr = Current();

   Sleep(500);
    felaps = Current() - fcurr;
  printf("\n current = %f       \n elapsed = %f      \n", fcurr, felaps  );
  };



  return 0;
}

консоль:

current = 266797.468750
elapsed = 0.500000

current = 266797.968750
elapsed = 0.500000

current = 266798.468750
elapsed = 0.500000

current = 266798.968750
elapsed = 0.500000

current = 266799.468750
elapsed = 0.500000

current = 266799.968750
elapsed = 0.500000

current = 266800.468750
elapsed = 0.500000

current = 266800.968750
elapsed = 0.500000

#28
19:21, 7 окт. 2010

ksacvet777
еще желательно выложить, такой же тест... без вызовов QueryPerfomanceFrequency
и показать где QPC плавает, а то вы сдесь мозги делаете, а мелкомягкие используют его где можно и не парят мозг,
XNA, WPF, весь .Net везде юзается тупой QPC и еще влом искать но я гдето читал, что QueryPerfomanceFrequency
может поменяться только после перезапуска системы, хотя я могу ошибаться на счет частоты, но то что мелкософт по этому поводу не заморачивается это точно

#29
20:38, 7 окт. 2010

Executor
> Так косяки кода или особенность операционки? :)
Если твой код не корректно себя ведёт из-за особенностей операционки, то наверное это проблемы кода :)
> Разница огромная, уже писал всё это десять раз... Разговор не о том...
Какое решение ты ждёшь? Сам ведь понимаешь, что при миграции с одного процессора на другой с таймером будут проблемы. Вариант, который ты показал в начале - вообще бред полный. Думай над архитектурой движка, чтобы можно было сразу на два ядра лечь, если тебя так волнует производительность.

Страницы: 1 2 3 48 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.