Блог страдающего Лиса
Lorem ipsum hello dolor sit world amet
10 окт 2024 Чт
Оптимизация? Не... не слышал
Есть у меня один проект одного ядра 8088, который я решил просто доделать, чтобы было. Суть такова. Существует такая инструкция как
Пришла пора значит, переделывать. Сегодня сел с утра и переделал так, что теперь вся эта инструкция выполняется за 4*CX + 3 тактов! Да, это вот такое ускорение аж в 3 раза! Один байт, получается, перекидывает за 2Т.
Если пересчитать количество тактов, то можно понять, что для того, чтобы сдвинуть экран 320 на 200, потребуется (160 x 4 + 3)*200 тактов, что равно 128600, и это в пересчете 25 000 000 / 128600 дает 194 кадров в секунду! Просто поразительное ускорение фактически на 300% только за счет того что я сделал оптимизацию.
Единственный минус в том, что если посередине исполнения этой инструкции возникнет сигнал INTR, то ему придется подождать, пока инструкция закончит работу. Учитывая, что там может быть 65535 итерации, то ждать придется 262140 тактов. Это надо учитывать при разработке программ, которые юзают INTR. Но и еще мне тоже надо доработать контроллер прерываний, чтобы не было такой ситуации, чтобы они были упущены, а то это нехорошо. Контроллер прерываний надо сделать внешний для этого.
А еще сделал чтобы STOSx выполнялся 1Т = 1 байт, с такой скоростью теперь пишется. Для LODSx вообще будет выполняться за 4-5Т всегда, вне зависимости от REP, поскольку имеет смысл читать только последние 1-2 байта из общей выборки.
Таким образом, я переделаю все строковые инструкции.
REP MOVSW
, например. Когда я делал это ядро раньше, то сделал ее такой, чтобы каждый раз она исполнялась за 12Т, и это очень, очень много! Несмотря на то что она исполнялась так медленно, даже этой скорости хватало, чтобы сделать скроллинг экрана со скоростью 65 кадров в секунду. Но разве это дело? Это медленно, и мне этой скорости не хватило.move: xor di, di mov si, 2 mov dx, 200 @@: mov cx, (318/2) rep movsw add di, 2 add si, 2 dec dx jne @b retВыше я привел сакральные коды скроллера, который выполняет перенос всего экрана. Итак, как мы видим, краеугольный камень проблемы в том, что rep movsw выполнялась за 12Т на каждое пройденное машинное слово (2 байта). Я посмотрел в код и удивился, до чего я его не оптимально сделал.
Пришла пора значит, переделывать. Сегодня сел с утра и переделал так, что теперь вся эта инструкция выполняется за 4*CX + 3 тактов! Да, это вот такое ускорение аж в 3 раза! Один байт, получается, перекидывает за 2Т.
Если пересчитать количество тактов, то можно понять, что для того, чтобы сдвинуть экран 320 на 200, потребуется (160 x 4 + 3)*200 тактов, что равно 128600, и это в пересчете 25 000 000 / 128600 дает 194 кадров в секунду! Просто поразительное ускорение фактически на 300% только за счет того что я сделал оптимизацию.
Единственный минус в том, что если посередине исполнения этой инструкции возникнет сигнал INTR, то ему придется подождать, пока инструкция закончит работу. Учитывая, что там может быть 65535 итерации, то ждать придется 262140 тактов. Это надо учитывать при разработке программ, которые юзают INTR. Но и еще мне тоже надо доработать контроллер прерываний, чтобы не было такой ситуации, чтобы они были упущены, а то это нехорошо. Контроллер прерываний надо сделать внешний для этого.
А еще сделал чтобы STOSx выполнялся 1Т = 1 байт, с такой скоростью теперь пишется. Для LODSx вообще будет выполняться за 4-5Т всегда, вне зависимости от REP, поскольку имеет смысл читать только последние 1-2 байта из общей выборки.
Таким образом, я переделаю все строковые инструкции.