Измеряем тики под MSDOS в 64/32 bit mode.

Тема в разделе "WASM.ASSEMBLER", создана пользователем Gray, 5 апр 2009.

  1. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    Быстрого кода, коллеги!

    Измерение времени выполнения кода здесь уже многократно обсуждалось и даже несколько программ на эту тему выкладывалось. Решил и я добавить в эту бочку меда свою ложку дегтя :)
    Идея в том чтобы из под MSDOS уйти в 64-bit mode и уже оттуда тестировать на кол-во тиков 64-х битный и 32-х битный код. Это позволит избавиться от мешающего точным измерениям переключения задач, жизнедеятельности других ядер и воспользоваться любыми привилегированными инструкциями процессора (наример сереализуемым WRMSR и WBINVD).
    Выкладываю исходник. Компилятор - FASM. Программа работает только под MSDOS! Рекомендую использовать MSDOS 5 или MSDOS 7 (от Windosw 98). С ними без проблем грузиться с флешки. Флешку удобно форматировать утилиткой HP USB Disk Storage Format Tool.
    Буду благодарен за любые комментарии и предложения по совершенствованию программы.
     
  2. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    Выкладываю на рапиду образ 2ГБ фпешки с MSDOS, Optcode и самым необходимым (архив 1 МБ)
    http://rapidshare.com/files/217820824/msdos7.rar.html
     
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Все конечно хорошо, но вы не подумали, что современный процессор под досом и на йоту не настроен, а те манипуляции, что вы делаете его настраивают не больше.
    1) многопроцессорность. может я не заметил (хотя вряд ли), но этого там нет. в целом при включении многопроцессорности производительность каждого отдельного ядра может существенно падать, но суммарная производительность будет значительно большей.
    2) память. вы считаете, что то, что вы с ней сотворили является достаточным. а подсчет производительности отдельных операций будет сильно зависеть от нее.
    3) прерывания. не плохо бы вообще все запретить.
    4) реальная скорость выполнения некоторых команд может зависеть от состояния кеша. я увидел у Вас там его очистку (из-за выравнивания аж на 256 байт), но не плохо бы проводить тесты с очищенным и не очищенным кешем, а также, замечу, что, относительно movsd, в кеше должны находиться также и страницы с источником и адресатом, а у вас там полный ахтунг.
    В целом программа не плохая, но чистота системы еще не означает, что отдача будет на 100%, и замените пожалуйста
    Код (Text):
    1. mov eax, cr0
    2. inc eax
    3. mov cr0, eax
    на
    Код (Text):
    1. mov eax, cr0
    2. or eax, 1
    3. mov cr0, eax
    или
    Код (Text):
    1. mov eax, cr0
    2. bts eax, 0
    3. jc already_in_PM
    4. mov cr0, eax
    а то, кто знает, что в досе может быть. может процессор уже в PM находится
     
  4. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    max7C4

    Именно об этом я и подумал. Под досом можно настроить так как тебе хочется и ОС не будет возмущенно кричать, что привилегированные комманды тебе запрещены. Конечно можно оптимизировать код в зашумленных другими процессами условиях, для этого есть, например, отличная программа от leo. Ее можно найти на этом форуме. Мне же хотелось сделать инструмент для измерений в произвольно настраиваемых пользователем условиях.
    Как раз с многопроцессорностью мне пришлось побороться. Рассказываю. Гонял я codeopt на ноутбуке Lenovo T400. Процессор Core 2 Duo P8600, FSB 1066 МГц, DDR3. Если оптимизируемый код к памяти не обращался, получались прекрасные результаты - разброс тиков практически нулевой. НО! если код читал/писал память разброс становился огромен, причем ненулевые результаты в tick-min шли полосами, т.е. группа нулей, потом группа больших значений, потом опять нули и т.д. Возникло подозрение, что второе ядро не спит, а чем-то своим занимается. Это под чистым досом то! К счастью в BIOS оказалась опция Enable/disable Multicore Processing. Disable помог. Похоже на этом ноутбуке BIOS как-то криво инициализирует второе ядро, либо запускает на нем какой-то процесс контроля. Дабы не делать этого в настройках BIOS пришлось поплясать с бубном. Результатом стало появление в OptCode строк:

    mov rcx,199h ; IA32_PERF_CTL MSR
    rdmsr
    mov [fs:PERF_CTL],rax
    xor rax,rax ; temporarily disengage opportunistic processor???
    ; mov rax,1000h ; bad. Don't use for single core mode!
    wrmsr

    Если раскомменттировать здесь одну строчку, появляются те самые "полосы". Подчеркну, что это именно результат плясок с бубном, ибо точное следование интеловским докам не помогло.

    Хм. Я не понял. А что я с ней сотворил?

    А разве я их разрешал? Для 64/32 даже обработчики прерываний отсутствуют. Кстати, хорошо что напомнили. Надо будет cli из начала TIMER64 и TIMER32 выкинуть :)

    Закомментированные строчки в TIMER64 перед циклом измерений:

    ; mov rax,[rsi]
    ; mov rax,[rdi]
    ; wbinvd ;2 bytes opcode 0F 09

    и перед wrmsr внутри цикла

    ; wbinvd ;2 bytes opcode 0F 09


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

    А код для проверки на PM вставлю. Спасибо! Действительно, вдруг кому-то захочется запускать OptCode под дос из под какого-нибудь дос-экстендера :)
     
  5. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    А второе ядро никогда не спит. просто это зависит от того что ему дадут делать. При Disable, я так понимаю, BIOS эмитирует одно ядро, а второму дает крутиться в бесконечном цикле ожидания без обращений к памяти.
    cli. я думал что он запрещает не все прерывания (но я правильно думаю, NMI не усыплен).
    добавьте что ли (по приколу, перед установкой PM)
    Код (Text):
    1. mov al, 255;маска. никого не пускать
    2. out 0xA1, al;замаскировать прерывания на втором контроллере
    3. out 0x21, al;замаскировать прерывания на первом контроллере
    да даже банальный emm386.exe. если он установлен, то дос работает уже в PM
    тут скорее дело не в том что вы сотворили, а чего не сотворили. под виндой устанавливая драйвера на чипсет вы ставите программу, которая также обеспечивает его тонкую настройку в данной системе. под досом этих алгоритмов и в помине нету. а контроллер памяти инициализирован по минимому BIOS'ом.
     
  6. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    Не уверен, что никогда не спит. Возможны варианты: от тривиального jmp $, или hlt, до установки какого-то усыпляющего битика, если мне память не изменяет, в CR8 или MSR. Надо будет в доках покопаться...

    А я в простое душевной предполагал, что переход в PM автоматически запрещает и NMI тоже :)
     
  7. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    но оно же все равно не отключается полностью. хотя при данном коде использует только загруженную в кэш линию, а вот память от него отключить не плохо было бы
    везде где читал советуют отключать и NMI тоже. тем более это хужее не сделает. тем более кто знает. вот к примеру himem при обращении временно переходит в PM, а при возврате восстанавливает REAL, но из-за этого прерывания могут снести вашей программе крышу. кто знает как himem их настроит
     
  8. Gray

    Gray New Member

    Публикаций:
    0
    Регистрация:
    6 окт 2004
    Сообщения:
    75
    Адрес:
    Russia
    Выкладываю поправленный по замечаниям max7C4 исходник.

    max7C4
    ИМХО, это невозможно. Думаю, что самое мудрое было бы отправить второе ядро в shutdow state. Пытаюсь разобраться как...

    Еще есть подозрения, что на стабильность результатов может влиять рефреш памяти.
     
  9. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Рефреш это одно из того, что входит в тонкую настройку памяти;)
    За исправления спасибо.
     
  10. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    max7C4
    и замените пожалуйста на
    Код (Text):
    1. mov eax, cr0
    2. or eax, 1
    3. mov cr0, eax
    Плохо, батенька, советуете. Я обожаю так - or al,1
     
  11. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Memphis
    это батенька Вам ДОС, а не чистая машина. так что надо бы проверить за одно установку этого флага.
    Код (Text):
    1. mov eax, cr0
    2. or eax, 1
    3. mov cr0, eax
    этой проверки не делает, а вот
    Код (Text):
    1. mov eax, cr0
    2. bts eax, 0
    3. jc already_in_PM
    4. mov cr0, eax
    в cf возвращает старое значение бита и такую проверку можно пройти за 4 команды, а не за 5. писать короче.
     
  12. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    max7C4
    это батенька Вам ДОС, а не чистая машина - а какая, хрен, разница. Чистый/грязный ДОС, виртуалка... Речь то не про это, а про корявость твоего кода. Еще раз напомню, что ты там написал -
    Код (Text):
    1. mov eax, cr0
    2. or eax, 1
    3. mov cr0, eax
    Узнал свою поделку ?

    А я всегда пишу так -
    Код (Text):
    1. mov eax, cr0
    2. or al, 1
    3. mov cr0, eax
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Memphis
    В большинстве случаев важнее скорость, чем размер. Имхо 32-х битный код в общем исполняется быстрее. Так что замените батенька на or eax,1.
     
  14. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Memphis
    Ну вот. Clerk опередил. спасибо Clerk.
     
  15. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    Clerk
    max7C4
    Речь не про большинство случаев, а про этот конкретный. Значит, утверждаете, 32-х битный код исполнится быстрее (лень третий раз фрагмент кода приводить) при переключении из Реала (значит еще в Реале) в Протект ?
     
  16. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    в этом случае да. тем более что речь даже не о размере команды, а о задержке при обращении к части большого регистра (Xx) или части расширенного регистра (eXx)
    тут она будет из-за eax/al/eax зависимости и обращении к части большого регистра
    Код (Text):
    1. mov eax, cr0
    2. or al, 1;0x80 0x08 0x01
    3. mov cr0, eax
    тут она будет из-за eax/ax/eax зависимости и обращении к части расширенного регистра
    Код (Text):
    1. mov eax, cr0
    2. or ax, 1;0x83 0x08 0x01
    3. mov cr0, eax
    тут она будет из-за eax/eax/eax зависимости и из-за использования префикса
    Код (Text):
    1. mov eax, cr0
    2. or eax, 1;0x66 0x83 0x08 0x01
    3. mov cr0, eax
    P.S.
    кстати. оцени новую дьрь. Ctrl+V называется. клево вставляет
     
  17. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    max7C4
    оцени новую дьрь - видать не в коде ты силен, а в словоблудии...
    Наверное, наизусть заучил некоторые фрагменты кода и вставляешь их налево/направо, не задумываясь. И невдомек человеку - бывает красивше.
    Кстати, or al,1 - кодируется 2-мя байтами (0Ch, 01), что в 16-ти, что в 32-х битке, и по времени одинаково пойдет в обеих, знаток ты наш хре...
     
  18. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Memphis
    да какая разница. действие последовательностей и тех и этих байт одинаковое, но
    в любом варианте команды код будет чуть медленнее. в одном случае из-за префиксов, на декодирование которых тратится время, в другом случае процессор будет вынужден декодировать команды по очереди т.к. не сможет сразу оценить прикол с частями регистров.
    Код (Text):
    1. mov eax, cr0;0x200F 0xC0 вот тут процессор создает лок. копию регистра eax и кладет туды значение из cr0
    2. or al, 1;0x0C 0x01 будь по вашему, возьмем короткий код. тут он не смекает, что eax меняют полностью и производит дополнительное копирование в новую копию eax, всвязи с чем появляется дополнительная задержка
    3. mov cr0, eax;0x220F 0xC0 а тут он сохраняет в cr0 вторую копию eax с установленным 0 битом и вынужден почистить 2 значения регистров, а не одно, если бы стояла команда or eax, 1.
    тут дело как раз таки в том, что вы кажется не знаете что произошло с процессором, когда в него встроили конвеер. чем меньше частичных регистров вы используете, тем быстрее получается код и тем меньше задержек исполнения из-за выявления ложных зависимостей. а они то как раз в основном появляются из-за того, что программисты стремятся сокращать код и используют большое число частичных регистров в то время как использование одного имени регистра во всем "микроалгоритме" (не большой части, куске всего алгоритма) не вводит процессор приводит к выравниванию микроопераций и устраняет ложные зависимости. к тому же можно очень сильно это распараллелить если учесть особенности конвееризации
    к примеру так
    Код (Text):
    1. mov eax, cr0;N (не помню точно сколько, но точно больше 1, смотреть влом) моп пойдет на 1 конвеер
    2. or eax, 1;1 моп (а не 2 в случае с or al, 1 из-за ложной зависимости) пойдет на 2 конвеер
    3. mov ecx, 0xXXXXXXXX;1 моп пойдет на 3 конвеер (имея ввиду P6)
    4. mov cr0, eax;N (не помню точно сколько, но точно больше 1, смотреть влом) моп пойдет на 1 конвеер
    тем самым мы не потратим время на декодирование mov ecx, 0xXXXXXXXX на 1 конвеере, а прогоним ее на 3 параллельно с первыми 2
     
  19. Memphis

    Memphis New Member

    Публикаций:
    0
    Регистрация:
    23 окт 2008
    Сообщения:
    104
    max7C4
    да какая разница. действие последовательностей и тех и этих байт одинаковое - разумеется, бесспорно. Ну почему вы все время твердите про быстродействие ? Даже, если ваш код окажется на пару тактов быстрее (надо еще доказать) - это не сыграет большой роли - фрагмент исполняется единожды (вместо тысяч/миллионов раз в цикле). В данном случае главнее другое - экономия байт памяти. Да, 2 байта, это не много. Но если грамотно "насобирать" по 1/2 байта в 100/1000 фрагментов - будет немало.
     
  20. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Memphis
    В любом случае под досом остается
    Код (Text):
    1. mov eax, cr0
    2. bts eax, 0
    3. jc already_in_PM
    4. mov cr0, eax