PDA

Просмотр полной версии : ускорить Unreal Speccy ? timeBeginPeriod()



S.T.A.S.
15.03.2005, 15:29
Здравствуйте!

Хотется подельтся некоторыми соображениями о эмуляторе.
В ini файле есть такая строка:
; give idle timeslices to other applications
ShareCPU=1 ; 1 - only for fast CPUs (incompatible with SoundDrv=none)Если флаг установлен, то эмуль отдаёт время CPU вызывая Sleep(SLEEP_DELAY). По умолчанию SLEEP_DELAY = 2.

На самом деле, в ОС NT задержка получается совершенно другая. Её время определяется ключём
HKLM\SYSTEM\CurrentControlSet\Control\PriorityCont rol\Win32PrioritySeparation
и составляет (на не серверных версиях) ~15мс.

Измерить время можно, поместив в файл emul.cpp (после стандартных хидеров) код:
#define SLEEP_TIMING
#ifdef SLEEP_TIMING
unsigned _tsc;
#define Sleep(X) _tsc = rdtsc(), Sleep(X), \
printf("Sleep(%u) time = %u microseconds\r\n", \
X,((rdtsc()-_tsc)/(conf.cpufq/1000000?conf.cpufq/1000000:1)))
#endif На практике числа могут быть иные (см. далее)

Так как длительность кадра Спектрума составляет =20мс, то мулятору при [VIDEO]VSync=1 нужно уложиться в оставшиеся 5мс для вывода кадра. Иначе возможны тормоза. Причём виновата в этом ОС :|

Документированных способов влиять на планировщик мне не известно, но есть полудокументированный - вызвать где-нибудь при инициализации timeBeginPeriod(1). При этом точность Sleep станет на порядок выше (реально: аргумент_ф-ции+1мс).
Теоретически, это должно позволить мулятору работать на более слабых машинах, чем сейчас.

timeBeginPeriod(1) можно вызывать из любой программы, поэтому, скорость работы эмуля может сильно различаться в зависимости от конфигурации софта (afaik, winamp и некоторые плагины миранды вызывают эту ф-цию).

У меня проц AXP2000+, но при SoundDrv=none fps падает до 35, поскольку Sleep() вызывается в цикле (2*15мс) - с включеным звуком этих проблем нет. При использовании timeBeginPeriod всё нормально ;)
Думаю, такая фича окажется полезной ещё для кого-то.

ЗЫ: На всякий случай аттачу отдельный тест для измерения Sleep и примитивную прогу, которая делает timeBeginPeriod(1) (пока не закрыт MessgeBox) - проверить можно не перекомпилируя эмуль.

Alchemist
15.03.2005, 19:11
Какой смысл вообще делать Sleep? Ведь эмулятор не расчитан на работу в фоне, поэтому большого смысла делать Sleep нет. Критические задачи все равно заберут время, если захотят.
В крайнем случае, можно делать Sleep(0).

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.

SMT
15.03.2005, 19:43
на селеронах под w2003 не наблюдаю никакого эффекта от timeBeginPeriod(), время выполнения Sleep(2) - от 2000 до 2800 mcs (а сколько у Вас?). завтра попробую на атлонах-1200,1333. в любом случае, это объясняет торможение на атлонах, про которое многие жаловались. а при sounddrv=none если задержка сделана на 30ms, следующей задержки не будет, то есть 30,0,30,0 - в среднем поддерживается 50 fps

Vladimir Kladov
15.03.2005, 19:55
на моем эмуляторе эта функция вызывается еще где-то с версии 2.4. Эффект = 0. Помогло другое: внешняя dll с хуком на ВСЕ процессы в системе, которая через маппированный файл "общается" с моим приложением" и как только истекает очередной период ожидания, пытается сделать sleep(0) в контексте текущей задачи. Т.е. самым что ни на есть грубым образом "отбирает" моему эмулятору приоритет. Иначе никакой плавности, кроме может быть в полном экране... Но в полном экране я просто врубаю high priority. Вот такие дела. Не реального времени ОС - windows...

S.T.A.S.
16.03.2005, 08:58
Какой смысл вообще делать Sleep?Если не делать этого (или делать Sleep(0) - управление вернётся сразу же), то занятость проца будет 100%. Из-за этого, например, нельзя поднимать приоритет потоку эмуля.
Другие задачи заберут время не когда захотят сами, а когда это решит планировщик. Он это обычно делает когда не нужно, и забирает всё сразу :) в результате возможны заметные "паузы" в работе раз в несколько секунд.


на селеронах под w2003 не наблюдаю никакого эффекта от timeBeginPeriod(), время выполнения Sleep(2) - от 2000 до 2800 mcsПод w2003 тестировать возможности не было (только 2K Pro, XP, +/- несколько разных SP), результат везде одинаков - 15мс. Может быть MS внесли изменения в работу планировщика?

Всё же, я думаю дело в каких-то других прогах, так как timeBeginPeriod имеет глобальный эффект. Можно попробовать закрыть всё лишнее (у меня влияет kX Mixer). К CPU это IMHO отношения не имеет - то же самое наблюдалось и на 4м пне с HT (измерялось моим тестом). Но быстрый проц успевает уложиться в оставшееся время.

Вот мои тесты на чистой 2K (под XP тоже самое)
// без предварительного вызова timeBeginPeriod
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

// предварительно запускается wait.exe - "изолированный" порцесс, делающий timeBeginPeriod
CPU AuthenticAMD at 1666 MHz
running Windows NT 5.0.2195
Sleep(1) time = 1952 microseconds
Sleep(1) time = 1953 microseconds
Sleep(1) time = 1952 microseconds

в полном экране я просто врубаю high priorityIMHO если периодически отдавать время системе (только уж не по 15мс), то можно повысить приоритет и в оконе, особенно если на переднем плане. Только если где случится jmp $, то труба :)
А с хуками - хитро, это уже хирургия :)


ЗЫ: Всё сказанное про слип не вкоем случае не относится к мастдаям - там точность хорошая.