Люди! Используя Sleep, 1 мы добиваемся задержки в 1 мс. Вопрос как получить задержку меньше этого значения порядка в 10 раз и чтобы не жрала проценты CPU? Есть возможно решить данную проблему заданием n-ого числа тредов. Можно ли иначе?
меньше этого значения порядка в 10 раз Тогда это будет около 100 мкс. Вряд ли это получится из user-кода, учитывая, что (например) в 98-ой таймер шлепает примерно ~600 мкс. На форуме vingrad.ru недавно было обсуждение метода на основе rdtsc на основе определенной заранее частоты cpu. В любом случае практически любой код из user-mode имеет недостаток быть прерванным высокоуровневым сервисом.
>> Используя Sleep, 1 мы добиваемся задержки в 1 мс Используая Sleep, максимум, чего ты можешь добиться, это 10 мс, даже если напишешь Sleep( 1 ). Держи пару идей из моего source кода: Идея первая: void TestTimeDelay( DWORD wMs ) { LARGE_INTEGER freq; LARGE_INTEGER count_start; LARGE_INTEGER count_end; LONGLONG count_dif; HANDLE hndl; hndl = GetCurrentThread(); SetThreadPriority( hndl, THREAD_PRIORITY_TIME_CRITICAL ); QueryPerformanceFrequency( &freq ); QueryPerformanceCounter( &count_start ); while ( 1 ) { QueryPerformanceCounter( &count_end ); count_dif = count_end.QuadPart - count_start.QuadPart; if ( count_dif >= freq.QuadPart / ( 1000 / wMs )) { break; } } SetThreadPriority( hndl, THREAD_PRIORITY_NORMAL ); } Идея вторая: void CAvi::StartMmTimer() { m_lCurTime = AVIStreamStartTime( m_pAviStream ); pPlay = this; timeBeginPeriod( 1 ); m_hMmTimer = timeSetEvent( m_wDelay, 0, TimerCallback, 0, TIME_PERIODIC ); } void CALLBACK TimerCallback(UINT, UINT, DWORD, DWORD, DWORD) { CAvi::pPlay->PaintStuff(); } Дело было четыре года назад, так что я точно не помню, чтобы описать всё в деталях. Но точно помню, что первое было проверено на осциллографе, и задержка была РОВНО 1 Мс. Второе тоже работало чётко в качестве mulimedia timer. Так что дерзай. Удачи
Avalonec Напиши, для каких целей это нужно. Решения для общего случая afaik не существует - виндос не является ОС реального времени. Sokol_2 > Странно, у меня получается точность намного лучше. Или это для мастая? (хотя и там у тоже точность лучше. дааже под VMWare) Мультимедиа таймер не поможет: Код (Text): timeBeginPeriod The timeBeginPeriod function sets the minimum timer resolution for an application or device driver. MMRESULT timeBeginPeriod( UINT uPeriod ); Parameters uPeriod [b]Minimum timer resolution, in milliseconds[/b], for the application or device driver. timeGetDevCaps возвращает TIMECAPS.wPeriodMin = 1 Если звуковая карта поддерживает аппаратное микширование, то можно поиграться со звуковым буффером, но это не является решением для 100% случаев :-(
Чтобы не быть прерванным просто необходимо поставить у родительского процесса самый высокий приоритет и у треда TIME_CRITICAL, таким образом можно добиться гарантированно задержки в 1 мс, что точно для приотрета равного 31. Мне нужно работать в некоторых участках кода значительно быстрее, чем в других, но в медленных участках кода и так уже стоит Sleep, 1, хотелось бы этот предел отодвинуть. Один из таких случаев: я работаю со множеством sock-потоков (для этой цели у меня написан отдельный модуль) и на localhoste получается скорость значительно выше если обработчик крутиться в прямом цикле без Sleep, но это и так понятно, самое главное проц грузится на 99%, а вот это не хорошо. Можно сделать многотредовостью. Но вопрос: сколько жрет у системы сам тред?
> что бы не быть прерванным, этого не достаточно - юзерлендный код всегда работает на уровне IRQL PASSIVE_LEVEL, так что его может прервать почти что угодно. А для задержки в 1 мс imho хватит и 15го приоритета (но во всяких мастдаях вроде не всё так хорошо) > То есть основная задача - снизить видимую загрузку на проц? Можно попробовать Sleep(0), возможно в цикле с выходом по условию (но только не с THREAD_PRIORITY_TIME_CRITICAL). > если у тебя всего один трэд - используй несколько, ресурсов процессора это не отнимает.
IRQL PASSIVE_LEVEL Да, это ты прав. А для задержки в 1 мс imho хватит и 15го приоритета (но во всяких мастдаях вроде не всё так хорошо) Как показывает практика временные задержки в винде сильно "плавают". И подобного уровня приоретета у меня не хватает. Задача, крутиться в цикле проверок как можно чаще, не отнимая значимого времени у проца. Sleep, 0 жрет 99%. Она может прокатить когда тредов с такимже уровнем в системе будет достаточно много, но это не подходит у каждого пользователя запущено определенное число задач. если у тебя всего один трэд - используй несколько, ресурсов процессора это не отнимает. Не один (5), но увеличить думаю можно. Тред жрет время самой системы - переключение задач, нитей и т.д. Вопрос в том как много?
Ну, переключение всё равно постоянно происходит - кол-во твоих потоков на это не влияет. И время переключения контекстов тоже не зависит от того, на какой конкретно поток переключается... Время работы самого планировщика как-то будет зависить от количества потоков, но этим imho можно пренебречь. Вот с кэшем сложнее, это может как-то влиять, но не думаю, что сильно. Хотя, это конечно всё мои измышлизмы
Время работы самого планировщика как-то будет зависить от количества потоков, но этим imho можно пренебречь. Если они правда не переваливает за сотню.
2 S_T_A_S Вышеупомянутый код прогонялся на Windows NT. Именно тогда я и столкнулся с этой проблемой: звал Sleep( 1 ), но задержка была в несколько раз больше. Может, сейчас Мелкософт ету проблему как-то пофиксил. Но верить им... эх, сам знаешь...
у меня сейчас: процессов 41, потоков 453... Ты в своей программе попробуй 100 создать и загрузить как-нить, в этом то и дело. Все эти потоки прозябают в бездействии. Вышеупомянутый код прогонялся на Windows NT. Именно тогда я и столкнулся с этой проблемой: звал Sleep( 1 ), но задержка была в несколько раз больше. Может, сейчас Мелкософт ету проблему как-то пофиксил. Но верить им... эх, сам знаешь... Она и сейчас минимум в 10 раз больше.
Код (Text): CPU AuthenticAMD at 1666 MHz running Windows NT 5.1.2600 Service Pack 2 Sleep(1) time = 1943 microseconds Sleep(1) time = 1954 microseconds Sleep(1) time = 1952 microseconds Sleep(1) time = 1955 microseconds Sleep(1) time = 1954 microseconds Sleep(1) time = 1953 microseconds Sleep(1) time = 1954 microseconds CPU AuthenticAMD at 1666 MHz running Windows 4.10.2222 A Sleep(1) time = 2571 microseconds Sleep(1) time = 957 microseconds Sleep(1) time = 1248 microseconds Sleep(1) time = 1123 microseconds Sleep(1) time = 1570 microseconds Sleep(1) time = 1008 microseconds Sleep(1) time = 886 microseconds CPU AuthenticAMD at 1666 MHz running Windows 4.0.1111 B Sleep(1) time = 894 microseconds Sleep(1) time = 1003 microseconds Sleep(1) time = 1049 microseconds Sleep(1) time = 937 microseconds Sleep(1) time = 997 microseconds Sleep(1) time = 990 microseconds 2 последних теста выполнены под VMWare, так что точность не слишком хорошая. Исходники и экзешник теста - в аттаче. Как вы получили ?! Аргументы вроде imho тоже самое, что "раньше был и метр больше, и килограм тяжелее" _793401770__sleep_test.zip
S_T_A_S_ Действиельно, задержка больше примерно в два раза. Такая серьезная погрешность закралась в расчеты, как оказалось, из-за активного использования процедур винды. Дело в том, что в треде я сделал обработку объектов-точек, которые двигались по экрану, отрисовка делалась посылкой WM_PAIN. Может кому пригодится версия на masm'е - attach. _1711162765__Sleep_time.rar
Пришлось мне тоже установить какую-то виндос 2000, совсем без сервиспаков (судя по билду вроде не бета), результаты такие: CPU AuthenticAMD at 1666 MHz running Windows NT 5.0.2195 Sleep(1) time = 15623 microseconds Sleep(1) time = 15625 microseconds Sleep(1) time = 15600 microseconds Sleep(1) time = 15633 microseconds Sleep(1) time = 15627 microseconds Sleep(1) time = 15631 microseconds Sleep(1) time = 15637 microseconds наверное, не зря микрософт сервиспаки делает
Реальная 98SE без всяких там виртуалок на P3-1000CPU GenuineIntel at 1000 MHz running Windows 4.10.2222 A Sleep(1) time = 997 microseconds Sleep(1) time = 991 microseconds Sleep(1) time = 997 microseconds Sleep(1) time = 1001 microseconds Sleep(1) time = 1001 microseconds Sleep(1) time = 996 microseconds Sleep(1) time = 1003 microseconds Sleep(1) time = 996 microseconds Sleep(1) time = 998 microseconds Sleep(1) time = 997 microseconds Sleep(1) time = 1001 microseconds Sleep(1) time = 1003 microseconds Sleep(1) time = 985 microseconds Sleep(1) time = 1008 microseconds Sleep(1) time = 996 microseconds Sleep(1) time = 1003 microseconds Sleep(1) time = 987 microseconds Sleep(1) time = 997 microseconds Sleep(1) time = 1007 microseconds Sleep(1) time = 994 microseconds XP - хлам.
По моему от сервиспака мало что зависит, это получено на реальной машине: CPU AuthenticAMD at 1206 MHz running Windows NT 5.1.2600 Service Pack 2 Sleep(1) time = 15594 microseconds Sleep(1) time = 15620 microseconds Sleep(1) time = 15637 microseconds Sleep(1) time = 15630 microseconds Sleep(1) time = 15634 microseconds Sleep(1) time = 15637 microseconds
Тест не корректный. Все зависит от присутствия/остутсвия других активных тредов и их приоритетов. Если в системе есть другой активный тред, то при вызове Sleep(1) планировщик отдаст ему временной слайс, величина которого зависит от системы. Для серверов это может быть 50мс например.