На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> инструкция Dec оказывается работает медленнее Sub
    Установил супер профайлер AQTime 6.21, который анализирует время работы кода построчно.
    Взял в Delphi написал тупой код см. вложение (большие числа слева это машинные циклы на выполнение данной инструкции), и профайлер показал, что DEC работает медленнее чем sub.
    Как это?

    Прикреплённый файлПрикреплённый файлpic.JPG (41,88 Кбайт, скачиваний: 511)
    Сообщение отредактировано: DelphiLexx -
      На время выполнения инструкций влияют еще и предыдущие. Попробуй попереставлять инструкции местами и будешь приятно удивлен, как меняется их доля :) Вообще же DEC не модифицирует регистр флагов полностью, поэтому возможны задержки из-за предыдущих команд, затрагивающих этот регистр. Собственно поэтому на современных камнях не рекомендуют использование DEC.
        Достаточно заглянуть в маны от интела, найти там подробнейшую информацию по инструкциям.
          Цитата Intel® Pentium® 4 and Intel® Xeon™ Processor Optimization.pdf
          InstructionLatencyThroughputExecution Unit
          ADD/SUB0.50.5ALU
          DEC/INC10.5ALU
          Т.е. DEC занимает полный цикл, SUB - только полуцикл.
            Цитата DelphiLexx @
            Установил супер профайлер AQTime 6.21, который анализирует время работы кода построчно

            :D На современных суперскалярных компах с внеочередным исполнением команд, достоверное профилирование на уровне каждой асм-команды практически невозможно. И твой пример это лишний раз подтверждает, т.к. самыми тормозными инструкциями в приведенном коде являются call и ret, а твой "супер профайлер" считает, что на исполнение call тратится времени меньше, чем на безобидный dec

            PS: Как-то на васме аналогичный вопрос всплывал по AMD CodeAnalyst - см. ответы #3 и #9

            Добавлено
            Цитата Qraizer @
            Т.е. DEC занимает полный цикл, SUB - только полуцикл.

            Это справедливо только для Pentium 4, а в P6 и AMD свои хитрости, и если после dec нет обращения к флагу CF (а в приведенном куске его нет), то dec отрабатывает также быстро, как и sub.
            Сообщение отредактировано: leo -
              Ну так я и сослался на доку по процессорам конретной архитектуры.
              Вообще, даже заняв полный цикл АЛУ, не факт, что будет падение производительности. Это зависит ещё от востребованности этого АЛУ другими микроопсами. Там на картинке видно множество АЛУ-команд рядышком.
              И, кстати, call/ret по картинке же на деле могут предсказываться с 100% точностью за минусом самого первого call. Медлительность ret объясняется, наверно, зависимостью по стеку от предшествующих pop.
                Цитата Qraizer @
                И, кстати, call/ret по картинке же на деле могут предсказываться с 100% точностью за минусом самого первого call. Медлительность ret объясняется, наверно, зависимостью от предшествующих pop по стеку

                Во-первых, предсказание тут ни причем, т.к. оно влияет только на задержку исполнения следующих за call\ret команд, а сами call\ret как ни крути состоят не из одной микрооперации как sub, и не из двух как dec в P4, а не менее чем из 3-х - запись\чтение адреса возврата, изменение esp и собс-но сам jmp (несмотря на предсказание, jmp как моп по любому должен "выполниться" только ради того, чтобы "отметиться" :) )

                Добавлено
                Еще раз подчеркну, что "построчный" анализ на уровне отдельных команд не может дать достоверной картины. Не знаю, как там в AQTime, а в справке по CodeAnalyst поясняется, что все это "построчное" профилирование выполняется путем прерывания процессора в случайные моменты времени и анализа того, на какой инструкции произошел останов. Спрашивается с какой стати он будет происходить именно на самой медленной инструкции, а не на следующей за ней ? Разве команда не обязана завершиться, если прерывание пришло в момент ее исполнения. Может тут dec и дает завышенное значение потому, что она идет вслед за ret и можно лишь примерно указать "проблемное" место в районе ret->dec

                Добавлено
                Кстати, вообще вопрос интересный, каким образом можно прервать (извне) исполнение кода на произвольной команде, если проц обрабатывает одновременно до трех простых одномоповых команд - они и с декодера могут поступать одновременно по 3 шт. и также тройками уходят в отставку (считаются выполненными) - спрашивается как ("на каком таком основании") внешнее прерывание может вклиниться и разбить эту тройку ?
                Сообщение отредактировано: leo -
                  Цитата Intel® Pentium® 4 and Intel® Xeon™ Processor Optimization.pdf
                  InstructionLatencyThroughputExecution Unit
                  RET81MEM_LOAD, ALU
                  CALL51ALU, MEM_STORE
                  Ну да, Latency велико, но Throughput вполне на уровне. Два порта исполнения ещё занимают... В общем, вполне терпимо.
                  Вот ещё из старого нарыл.
                  Цитата Pentium II and Pentium III Processors Instruction to Decoder Specification
                  Instruction# of
                  mops
                  CALL rel16/32 near4
                  RET near4


                  Добавлено
                  Что касается внешних событий, нужно почитать. Думаю, внешние прерывающие сигналы просто отрабатывают, как соответствующие программные аналоги, эдакими неявными int.
                    Цитата Qraizer @
                    Думаю, внешние прерывающие сигналы просто отрабатывают, как соответствующие программные аналоги, эдакими неявными int

                    Программные аналоги отличаются тем, что их положение среди других команд строго определено. А внешние сигналы приходят в произвольный момент времени, когда в конвеере на разных стадиях уже крутится десяток-другой команд, причем простые одномоповые команды поступают и покидают конвеер по 3 шт. за такт, поэтому и не понятно как внешний сигнал может нарушить это "триединство", т.к. если привязываться к тактам, то "эдакий неявный int" можно вставить либо до, либо после очередной тройки команд. Загадка, одним словом...
                    Сообщение отредактировано: leo -
                      Я ж говорю, почитать надо. Помню, что i486 распознавал активность по сигналам INTR и NMI только на границах инструкций, кроме тех, которые специально оговорены, что после них этого не делается. Например, команды пересылки в SS, кроме LSS, запрещают восприятие активности по этим входам, что даёт возможность атомарно изменить пару регистров SS:(E)SP целиком. Так что последовательность
                      ExpandedWrap disabled
                        ALIGN 16
                        mov eax, OFFSET [newStack]
                        mov ss,  SEG    [newStack]
                        mov esp, eax
                      гарантирует целостность стека (даже с учётом страничных отказов). Обнаружив активность, процессор выполняет специальный цикл шины, отключающий другие задатчики от неё, и ждёт по линиям данных байта от PIC с номером прерывания. (Кроме NMI, его номер известен.) Затем снимает блокировку шины и переходит к исполнению неявного int с полученным байтом как imm8.
                        Цитата Qraizer @
                        Я ж говорю, почитать надо

                        Где ? В официальных мануалах о таких тонкостях не пишут, видимо считая это несущественным для асинхронных прерываний. Те же общие слова о границах инструкций, определяемых на стадии их отставки (retirement):
                        Цитата
                        The ability of a P6 family processor to speculatively execute instructions does not affect the taking of interrupts by the processor. Interrupts are taken at instruction boundaries located during the retirement phase of instruction execution; so they are always taken in the “in-order” instruction stream.

                        А то, что в "суперскалярах" в отставку могут уходить две-три инструкции одновременно - ни слова (в контексте определения момента прерывания)
                          Ну почему не пишут:
                          Цитата Intel® 64 and IA-32 Architectures Software Developer’s Manual \ Volume 3A System Programming Guide Part 1

                          6.15 EXCEPTION AND INTERRUPT REFERENCE
                          ...
                          Interrupts 32 to 255—User Defined Interrupts
                          ...
                          Description
                          ...
                          • Responded to an interrupt request at the INTR pin or from the local APIC when the interrupt vector number associated with the request is from 32 through 255.
                          ...
                          Saved Instruction Pointer
                          The saved contents of CS and EIP registers point to the instruction that follows the INT n instruction or instruction following the instruction on which the INTR signal occurred.

                          Program State Change
                          A program-state change does not accompany interrupts generated by the INT n instruction or the INTR signal. The INT n instruction generates the interrupt within the instruction stream. When the processor receives an INTR signal, it commits all state changes for all previous instructions before it responds to the interrupt; so, program execution can resume upon returning from the interrupt handler.
                          Исходя из этого можно сделать тот же вывод. Всё выбранное и декодированное после инструкции, на которой был замечен INTR, отбрасывается (ну или по меньшей мере не учитывается), процессор отрабатывает эту последнюю команду целиком, ордерит своё состояние и переходит к INT n, соответствующей исходной INTR.
                            Qraizer, ты че - не въезжаешь или издеваешься ?! :wacko:
                            Процессор - тактируемое устройство, поэтому внешний сигнал INTR может быть зафиксирован только с точностью до такта (об этом кстати однозначно говориться в спецификациях). Но за 1 такт в суперскалярах может декодироваться и исполняться до 3-х команд одновременно. Это означает, что команды могут группироваться в неразрывные пары или тройки, обрабатываемые за 1 такт, и соотв-но INTR м.б. "замечен" не на любой произвольной команде, а только на границах таких неразрывных групп.
                            В частности в приведенном примере #1 первые две команды в начале цикла (lea eax и mov edx) являются простыми одномоповыми и независимыми (ни друг от друга, ни от каких предыдущих команд), поэтому они декодируются, исполняются и уходят в отставку всегда парой и соотв-но внешний INTR (по идее) никак не может вклиниться внутрь этой пары таким образом, чтобы lea оказалась выполненной, а mov нет. Соотв-но EIP после INTR не может указывать на команду mov, т.к. в начале такта ухода этой пары в отставку EIP указывает на lea, а в конце такта сразу перескакивает на след.команду call
                            Сообщение отредактировано: leo -
                              Я прекрасно въезжаю в то, что ты хочешь сказать. Я не понимаю, что тебе тут не понятно. Ну и не получится никогда в жизни, чтоб INTR разбила эту твою пару пополам, вклинившись между ними. Ну и что? Да, отберуться из потока исполнения и будут переданы декодерам одновременно. Если я никогда не увижу в стеке EIP указывающий на MOV, кроме как если взведён TF или на неё указывает один из DRx, что я потеряю? Обработка же аппаратного прерывания всё равно описана, и описана чётко.
                                Цитата Qraizer @
                                Я прекрасно въезжаю в то, что ты хочешь сказать. Я не понимаю, что тебе тут не понятно

                                А зачем тогда приводишь цитаты не имеющие отношения к моему вопросу и вынуждаешь по три раза повторять одно и то же ? ;)
                                А непонятно мне то, что если AQTime и CodeAnalyst юзают внешние прерывания для определения процента времени выполнения инструкциий, почему для всех команд получается ненулевой процент - случайное стечение обстоятельств, или все же прерывание может вклиниваться в пары-тройки, или же существует какой-то более продвинутый метод "построчного" профилирования ?
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0795 ]   [ 16 queries used ]   [ Generated: 15.05.24, 05:49 GMT ]