Вообще новичек, подскажите пожалуйста, что оптимальней будет: - счетчик в цикле держать в памяти как переменную, копировать в регистр обновлять и проверять условием или постаянно его в стек скидывать (Push - Pop) востанавливать в регистр и апдейтить ... если я прально вникся в мануал по масму, то push- 1 clock, pop - 4 clock... того 5 а mov в переменную 1 и обратно 1 - того 2 .... но всё-таки меня терзают смутные сомнения ибо много кто стеком пользуется для подобных целей... провсветите меня гуру...
Код (Text): Usage: POP dest Modifies flags: None Transfers word at the current stack top (SS:SP) to the destination then increments SP by two to point to the new stack top. CS is not a valid destination. Clocks Size Operands 808x 286 386 486 Bytes reg16 8 5 4 4 1 reg32 4 - - 4 1 segreg 8 5 7 3 1 mem16 17+EA 5 5 6 2-4 mem32 5 - - 6 2-4 вроди 4 .... хелп по масму
Сначала пересмотрел свой источник. Латентность - 1. Потом посмотрел в справке масма (специально установил себе масм для этого). Табличка соответствует Вашей. Подумал, что в обоих случаях может быть фигня, и полез в мануал по оптимизации от Intel: наверное там самый верный вариант. А там: латентность - 1,5 такта, пропускная способность - 1 такт. Но в любом случае размерчик будет у push/pop поменьше.
Latency для push/pop одинакова: 1.5. Для mov - 1/0.5 (для моделей 0F3n/0F2n). "Хелп по масму" (opcodes.hlp) устарел. Правда, непонятно: разницы между mov reg,reg и mov reg,mem разве нет?
2 Booster нет конечно ... но команды те-же вроди... спасибо всем, кое-что для себя понял... кто знает где можно не устаревшую подобную табличку взять???
ZEQ, l_inc Это смотря что понимать под латентностью push\pop. Для современных процев полную латентность указывают только AMD - у них обе операции выполняются за 3 такта, начиная от запуска на исполнение и кончая получением данных из кэша. Intel же в свих таблицах латентностей приводит только регистровые операции, а об операциях с памятью говорит отдельно и советует добавлять для целочисленных операций +2 такта на чтение данных из кэша. Поэтому 1.5 такта на push\pop это не время считывания операнда из памяти, а время в течение которого push\pop читают и изменяет регистр esp
leo Спасибо. Ясно. ZEQ Насчет "не устаревшей таблички", думаю Intel® 64 and IA-32 Architectures Optimization Reference Manual с сайта Intel, раздел Instruction Latency and Throughput подойдет (Google сразу выдаст ссылку). Это по латентностям. В других их мануалах еще куча информации (включая длины инструкций и т.п.).
Только надо еще учитывать, что на большинстве современных процессоров, на считая Core2 операции со стеком повышают риск зависимости по esp, а буде таковая случится - темп выполнения будет ближе, к latency а не к throughput.
l_inc еще можешь посмотреть в сторону мануалов Агнера Фога. Лучше их использовать вместе, но на абсолютную истину расчитывать не приходится в любом случае - иногда проще руками померить... truth, как говорится out of there...
Ustus А разве throughput не есть задержка между повторяющимися инструкциями? Т.е. что значит ближе, если latency - это и есть темп выполнения инструкции (с учетом поправок, внесенных leo)? Ну... возможность распараллеливания в случае отсутствия зависимости повышает темп выполнения, но throughput вроде к этому не имеет отношения или не так?
l_inc Именно к этому и имеет отношение. Если грубо - цепочка зависимых команд будет выполнятся с темпом близнким к latency, а независимых - с темпом, близким к throughput. В реальности, однако, влияют еще некоторые факторы, так что истинный темп где-то посередине. Легче всего это пояснить примером: add eax, edx add eax, edx add eax, edx ... будет выполняться (на Athlon'е для примера, на нем проще прикинуть) с темпом ~1 инструкция за такт, а: add eax, edx add ebx, edx add ecx, edx add eax, edx add ebx, edx add ecx, edx ... ~3 инструкции за такт. Поэтому и считается, что для Athlon'овской ADD reg32, reg32 latency=1, throughput=1/3.
Ustus Странно. Я думал совсем по другому. Объясните, пожалуйста, с какого момента я начинаю нести чушь. Вот выдержка из мануала Интел: По аналогии с Вашим примером из цитаты следует (для Интел add Latency = 0,5 и add Throughput = 0,5): add eax, edx add eax, edx add eax, edx ... будет выполняться с темпом 1 инструкция за такт (собственно время выполнения инструкции, Latency, плюс время ожидания для повторного приема той же инструкции, Throughput), а: add eax, edx add ebx, edx add ecx, edx ... будет выполняться с темпом 1 инструкция за 0,5 такта (т.к. задержки Throughput нету)
l_inc С "плюс время ожидания", т.к. throughput отсчитывается с момента запуска инструкции на исполнение, а не ее окончания. Issue port - это порт запуска инструкции на исполнение. Если исполнительный блок сам по себе быстрый (ALU), то throughput порта = latency блока, т.е. инструкции могут исполняться непосредственно одна за другой (в т.ч. и зависимые). Причем если для данной операции предусмотрены несколько портов и исп.блоков, то цепочка независимых операций может разветвляться\параллелиться по нескольких портам и эффективный темп возрастает. Например, независимые add r,r на атлонах могут выполняться до 3-х за такт, а в P4 до 4-х (на двух fast ALU по 0.5 такта). Если исп.блок не очень быстрый, но конвееризованный, например, целочисленный умножитель, то порт может запускать следующую независимую инструкцию, не дожидаясь завершения предыдущей. В этом сл. throughput < latency, поэтому цепочка из n зависимых операций будет выполняться за n*latency тактов, а независимых за (n-1)*throughput+latency тактов (см.пример диаграммы) PS: чтобы тебя окончательно запутать, замечу что у хитрых Intel'ов операции fast ALU конвееризованы, т.е. на самом деле латентность add r,r составляет не 0.5 такта, а 1 такт, т.к. за 0.5 такта обрабатывется только половина операнда. Пока цепочка зависимых операций выполняется на блоках fast ALU такая половинчатая обработка работает нормально и эффективная латентность = 0.5. Но если результат должен использоваться в другом блоке, например в умножителе или вычислении адреса mov, то тут появляется доп.задержка в 0.5-1.0 такт (0.5 на готовность второй половинки + 0.5 на дискретность запуска в normal-speed порт) Код (Text): add eax,edx |xx|..|..|..| |.x|x.|..|..|..| add eax,edx |.x|x.|..|..| |..|xx|..|..|..| задержка >-<=0.5 >-<=0.5 add eax,edx |xx|..|..|..| |.x|x.|..|..|..| mov edx,[eax] |..|xx|xx|xx| |..|..|xx|xx|xx| задержка >--<=1.0 >----<=1.5
leo Я так понимаю, что имелась в виду цепочка независимых операций. Ладно. Тогда я не понимаю, почему Intel пишут, что add latency - 0.5. Либо нужно писать add latency - 1, add throughput - 0.5; либо вообще не имеет смысла различать понятия latency и throughput, если они пишут туда одно и то же значение, предполагая при этом, что add всегда будет выполняться в окружении независимых инструкций. А как же Ваш второй пример? Зависимая инструкция выполняется через такт (или даже полтора) после работы add.
l_inc неправильно выдрал из контекста: ключевые слова здесь - "выполняется на блоках fast ALU" - ибо только они могут работать на двойной частоте. Если результат потребуется другому исполнительному блоку, тот получит его никак не раньше начала целого такта. А насчет throughput -cейчас я тебя Совсем Запутаю! Дело в том, что в примере рассмотрен 1ALU, а у NetBurst их три - два быстрых и один медленный. Поэтому максимальный темп выполнения независимых add теоретически - две штуки за половину такта. Вообще, P4 в плане оптимизации/профилирования меня до сих пор пугает
Ustus Как раз понял, хотел исправить, а Вы уже ответили. Теперь ясно. Ustus, leo Спасибо за просветительную лекцию!
l_inc Нет именно зависимых, т.к. независимые могут и параллельно на разных блоках выполняться, а зависимые только последовательно. Но за счет конвееризации, fast ALU за 0.5 такта выдает младшую половину результата, которая сразу поступает на это же или второе fast ALU для выполнения следующей инструкции add, поэтому во втором полутакте параллельно вычисляется старшая половина результата первого add и младшая половина второго add Вот в этом и заключается лукавство интеловских писАк и политиканов Разработчики в своих академических журналах честно и достаточно подробно расписывают как работает fast ALU и говорят о 0.5 тактах как об effective latency, хотя на самом деле полная латентность составляет 1.5 такта (флаги операции выставляются только в третьем полутакте) См.первоисточник "The Microarchitecture of the Pentium 4 Processor" (Intel Technology Journal, 2001), а также мануальчики от А.Фога microarchitecture.pdf и instruction_tables.pdf - там все дополнительные (additional) латентности для P4\P4Е расписаны PS: о, я как всегда припоздал с сочинительством PPS: поправил ссылку на первоисточник, т.к первый вариант оказался битым