bogrus > "значит неправильно считает оверхэд на 28 тактов для P4 " 1. Возможная причина того, что на P4 твой wintest.exe дает overhead <> 0 в том, что, как мы уже выяснили, не нужно писать в секцию кода в одном килобайте с исполняемыми инструкциями. Вот результаты wintest.exe на P4-1800 (модель 15.2.7), FSB-400, DDR-(2x133MHz) i)голый тест без mov: первый проход либо 28 (на глаз ~30%) либо 280,292,300 (~70%) остальные стабильно - 28 ii)с включенным mov eax,[mem]: первый проход - порядка 31-38 тысяч остальные стабильно - 28 iii) переносим объявление секции code на метку start и получаем НЕЗАВИСИМО от того есть mov eax,[mem] или нет: первый проход - стабильно 48 остальные стабильно - 0 Здесь первый проход занимает мало времени потому, что [mem] оказывается в одной секции со служебными данными tics, overhead и т.д. и многотысячные задержки приходятся на служебную часть кода. Второй вариант отдалить данные от кода - это оставить служебные данные в секции кода, но перед start вставить align 1024. Тогда без mov имеем на первом проходе те же 48, а с mov знакомые 38 тысяч. iv) ОДНАКО стоит заменить mov eax,[mem] на mov [mem],eax получаем стабильно +24 тика во всех проходах (т.е. 72 в первом и 24 в последующих). Причем эта добавка +24 сохраняется если использовать до 4х mov [mem+disp],r32, затем от 5 до 7 mov имеем +28, при 8ми +32 (прирост с дискретом в 4 такта). Почему ? Видимо потому, что CPUID форсирует все незавершенные операции, включая выталкивание всех буферов записи в кэш и завершение всех транзакциий записи в память. Значит 1) время выполнения CPUID не постоянно и зависит от наличия незавершенных операций (и по Агнеру число мопов CPUID на P4 от 40 до 80), 2) при использовании CPUID мы можем получить время исполнения тестируемого куска (пишущего в память) вместе со скрытыми "довесками", которые процессор при обычной работе выполняет параллельно в фоновом режиме, а здесь мы заставляем его форсировать события. Хотя для простых регистровых операций получаются вполне "нормальные" результаты, НО опять таки в пределах нескольких тиков (+-4 на P4 и +-1 на P3). 2. Наверное, для "простых" инструкций типа mov eax,[mem] получить "нужное" число тиков на P4 (да и на P3) невозможно. Проверил я несколько известных "тормозных" инструкций на P4 - везде результат занижен на 4. Ведь за инструкцией идет xor eax,eax и cpuid. Сама cpuid состоит из множества элементарных микроопераций, из которых 4 поступают из trace cache, остальные из микрокод-ROM. Значит первые мопы cpuid могут параллелиться с тестируемыми инструкциями. А кто собственно говорит, что не могут ? Интел гарантирует только две вещи: 1) cpuid будет выполнена в логической последовательности команд без изменения порядка (т.е. предыдущие инструкции не могут быть переставлены за cpuid, а последующие перед ней) и 2) cpuid гарантирует полное завершение всех предыдущих операций до начала выполнения инструкции, следующей за cpuid. И все, насчет возможности "налезания" предыдущих мопов на cpuid ничего не говорится и по логике работы проца это возможно. Поэтому при расчете оверхеда мы имеем один результат, а при тестировании несколько мопов тестового кода могут перекрываться со вторым cpuid => получаем заниженные результаты (4 тика на P4 и 1-2 на P3). Хотя причина такой дискретности может быть и в другом. Экспериментируем дальше: раз несколько тиков все равно съедаются, то нет особого смыла после тестового куска использовать cpuid, тем более что он искажает результаты записи в память. Выкидываем xor и cpuid и смотрим варианты: сразу rdtsc, cld+rdtsc и clc+rdtsc (с подачи Агнера). Тут начинается небольшая куролесица. На P3 вроде бы появляется желанный +1 такт на mov, но при добавлении второго mov почему-то задержка не возрастает. Ну и прочая чехарда в пределах +-1 такта на быстрых операциях и больше на медленных (типа div). А причина может быть в хитростях изменения задержки декодирования инструкций в P6 family, что и Агнер особо подчеркивант в pentopt.pdf. На P4 такая же фигня, но уже с дискретом в 4 такта. Почему 4, фиг его знает... А вывод-то простой: ну низя "точно" определить время исполнения одной изолированной команды. И в смысле измерения, и в смысле логического определения (например, нужно ли учитывать время декодирования или выборки инструкции из кэша; или что есть mov m32,r32 - быстрая запись в буфер, или запись в кэш, или в память; ну и т.д и т.п.). И еще вопрос - а зачем это нужно, если реально команды работают в потоке и проц может переставлять и параллелить микрооперации разными способами в зависимости от окружения. Вот и надо проверять не отдельные команды, а блоки команд, циклы. И чем больше тиков тем лучше - тем меньше будут сказываться неточности метода измерения.
leo Урря, спасибо, значит теперь можно считать подсчет оверхеда и для P4. Да, это правильно, я сегодня немного почитал и Агнера и Касперски и Интела (и ты говоришь совершенно верно), ещё потестил этой же программой и понял, что нельзя говорить "эта одна инструкция занимает 1 такт", всё намного сложнее, но понять можно и замеры проводить можно (пусть и приблизительные т.к. сам процессор не предоставляет возможности замерить точное время выполнения команды), даже нужно все замерять, именно для того, чтобы ПОНЯТЬ как работает конвеер, декодеры, кеши ... Только пройдя через это, знания можно будет использовать на практике, при оптимизации, даже просто учитывать их "подсознательно". Кроме того, хоть какой-то, но будет "профайлер" Именно для мелких нужд, небольших циклов. Я сейчас тяну VTune (150 Мб), но пока он вытянется (несколько дней) ..., а так я уже могу читать Агнера и проверять на своем камне. Агнер "14. Раскодировка инструкций (PPro, PII и PIII)" Цитата "Из вышеприведенных правил следует, что декодеры могут генерировать максимум шесть мопов за такт, если первая инструкция в каждой раскодируемой группе разбивается на 4 мопа, а другие две - на один каждая. Минимальное количество - это два мопа за такт, если все инструкции генерируют по два мопа, так что D1 и D2 никогда не используются." Пробую "add reg,mem", у PIII это 2 мопа и соотв. не используют декодеры D1 и D2 (только D0), значит 3 таких инструкции должны забирать 3 такта, пробую - так и есть: Код (Text): ====================================================================== ====== Intel Celeron 666MHz Coppermine (Family 6 Model 8 Stepping 6) ====================================================================== ====== 1test.exe ====================================================================== ====== 00402455 | 0305 00104000 |add eax,[401000] ; 2 uops (D0) - 1 такт 0040245B | 0305 00104000 |add eax,[401000] ; 2 uops (D0) - 1 такт - 3 такта 00402461 | 0305 00104000 |add eax,[401000] ; 2 uops (D0) - 1 такт ============================================================================ Делаю второй тест, где три инструкции расходятся на 3 декодера, и получаю 1 такт, как Агнер и заявлял Код (Text): ====================================================================== ====== 2test.exe ====================================================================== ====== 00402455 | 0305 00104000 |add eax,[401000] ; 2 uops (D0) - 0040245B | 8B0D 00104000 |mov ecx,[401000] ; 1 uop (D1) - - 1 такт 00402461 | 41 |inc ecx ; 1 uop (D2) - ============================================================================ С помощью этих (RDTSC) тестов можно подсчитать время ДЕКОДИРОВАНИЯ инструкций (в тактах). Хотя ещё нужно разобратся с другими ядрами PIII, т.к. бывают отличные результаты (о P4 мне говорить трудно) Код (Text): ====================================================================== ====== Intel Celeron 500MHz Mendocino (Family 6 Model 6 Stepping 5) ====================================================================== ====== 1test.exe - 4 такта 2test.exe - 1 такт ====================================================================== ====== Intel Pentium III EB 666MHz Coppermine (Family 6 Model 8 Stepping 3) ====================================================================== ====== 1test.exe - 3 такта 2test.exe - 1 такт ====================================================================== ====== Intel Celeron 1000MHz Tualatin (Family 6 Model B Stepping 1) ====================================================================== ====== 1test.exe - 6 тактов 2test.exe - 5 тактов ============================================================================ _1581532283__wintest.zip
bogrus > "всё намного сложнее, но понять можно и замеры проводить можно" Как говориться - "можно если осторожно", если с умом, с научным подходом и априорными данными от Intel, Агнера и др. Для исследования и "постижения истины" это очень даже полезно. А вот для бездумных школяров, которым нужно спихнуть лабу и которые кричат "помогите, все пропало" и хотят "сравнить разные типы адресации по скорости", не имея вразумительного представления о предмете, - такие программы типа "вставьте сюда тестируемые инструкции" ИМХО могут только навредить. А посему советую тебе в свой wintest вставить краткий комментарий для двоечников, что не все так просто как кажется - шутка конечно
bogrus С нашими "попугаями", выдаваемыми wintest.exe есть некоторые проблемы на P4: 1) На популярных моделях 15.2.x (Northwood) оверхед считается нормально, но наблюдается устойчивая дискретность задержки тестируемых инструкций в 4 такта. Сегодня проверял варианты BitTest с Int64 - все результаты кратны 4. 2) На модели 15.3.4 (Prescott) имееем вообще полный хаос даже при переносе "технических данных" в отдельную секцию, особенно под XP. Под Win98 оверхед скачет между значениями 0, 1, 7 и 8 и результаты тестов тоже различаются на 7-8, 15-16 и 21-22 (похоже дискретность увеличилась до 8, но еще и нестабильность добавилась). Под XP sp2 результаты вообще не предсказуемые , поэтому и цифры не привожу - они различаются в десятки и сотни раз - ощущение полного хаоса. И это при установке высоких приоритетов process и thread. Возможно какая-то фигня с двухпроцессорностью - пресловутым гипер-трейдингом. Единственное утешение - эти монстры еще не очень распространены (насколько я слышал, толковые дилеры пока не рекомедуют с ними связываться), а возможно что и сдохнут как динозавры в недалеком будущем как "ошибка природы"... Чего в них хорошего - мегабайтный кэш с удвоенными-утроенными задержками выборки ?
bogrus На P-3 0 bytes 10 passes и все 0000, даже первый ============================ Intel Pentium III EB 866MHz ============ ====== Совпадает с 666 ! 1test.exe - 3 такта 2test.exe - 1 такт
Короче, предлагаю не юзать эти тестеры на P4 На PIII, можно, но только осторожно, для получения приблизительной картины. Для более точных расчетов, под Intel качаем VTune, под AMD - CodeAnalist
bogrus Ну если осторожно, то и на P4 (модели <= 2) можно. Для тестирования циклов вполне можно юзать, при условии, что общая задержка получается достаточно большой и мы не обращаем внимания на мелкие колебания. Ведь на P4 разумный выигрыш при оптимизации может составлять минимум 0.5-1 такт на цикл. Поэтому если мы берем цикл из 100 проходов, то разница в 0.5 тика на цикл должна дать нам сразу около 50 тиков разницы в результатах. Если заметно меньше, то и не стоит считать это выигрышем или проигрышем.
leo базара нет, тест показывает то, что и должен, а именно разницу TSC, от одной инструкции до другой, это уже можно использовать. Другое дело, что архитектура ядра + микрокод RDTSC, CPUID может, и сильно отличается от модели к модели, и потом: Агнер "14. Раскодировка инструкций (PPro, PII и PIII)" Цитата "Коды доставляются из кэша кода выравненными 16-ти байтными чанками в двойной буфер, в который умещается два таких чанка. Затем код поступает из двойного буфера в декодеры в виде блоков, названными мной "блоками доставки инструкций" (БДИ)." Кто знает, сколько декодеров у P4, какова длина конвеера у P4, какого размера у него буфер, или ещё чего? Еcc-но только в спецификации на конкретную модель, а тестируя цикл на оптимальное расположения инструкций, занятость конвеера, декодеров на своем камне, невозможно распространить тоже на другие модели. Один цикл можна оптимально сделать для PIII, но если на P4 "БДИ" будет загребать не 16, а 32 байта, то вся "параллелизация" может улететь наоборот, в постоянное "пенальти", особенную роль играет выравнивание. Что я вычитал о VTUNE, так он позволяет на моем PIII эмулировать P4, как выкачаю, то поделюсь мыслями о его возможностях. А wintest пригодится, чтобы в общих чертах понять влияние выравнивания, расположения данных-кода (менеджер памяти ОС тоже может влиять), да и тип памяти, частота системной шины ...
На P4 выравнивание кода и декодирование влияют только на первый проход, который мы пропускаем в wintest. Декодер на P4 всего один и декодирует одну инструкцию за такт. Код поступает из L2 32-байтными чанками. После декодирования последовательность микроопов сохраняется в trace-кэше L1. При повторных проходах мопы извлекаются из trace-кэша и поступают в реордер-буфер со скоростью 3 шт.за такт. Повлиять на выравнивание мопов в L1 ес-но никак нельзя. Отсюда следует: 1) "увидеть" работу P4 в режиме декодирования мы не можем из-за большие задержек в первом проходе; 2) при повторных проходах, когда декодированные мопы извлекаются из L1 "незначительные" перестановки инструкций мало влияют на общую задержку (в отличие от оптимизации декодирования на P3), хотя судя по Агнеру иногда могут наблюдаться изменения задержки на 1/3 такта. Общий вывод я для себя делаю такой: если мы оптимизируем цикл или часто вызываемую процедуру, и хотим, чтобы наш код работал сравнительно быстро и на P3 и на P4, то 1) следует проявлять осторожность при использовании "тяжелых" для P4 инструкций, т.е. избегать их или анализировать возможность распараллеливания с другими инструкциями. Представление о тяжести можно получить у Агнера или IA-32 Optim - сюда оносятся: сдвиги (>= 4 такта), LEA с масштабированиеми, SETcc\CMOVcc (5), ADC\SBB (8), битовые и строковые операции, а про BCD лучше вообще забыть. Да вообще на P4 чем проще инструкции, тем быстрее несмотря на некоторое увеличение их числа. При выборе компромисса между тиками на P3 и P4 можно иметь ввиду предполагаемое соотношение частот ~2-3 (например, лишние 4-5 тактов за счет сдвигов можно пережить, а вот 50-100 на BCD инструкциях никакими повышениями частоты "не выбрать"). 2) расположение инструкций выбирать исходя из оптимизации декодирования на P3. А ведь есть еще "малоизученные" Атлоны...
Что там малоизученого? Вот bogrus правильно делает - качает тулзу, которая ему поможет найти много ответов на вопросы А размышлять можно сколько угодно...
S_T_A_S_ Уже скачал утром (7.1А), и ну его НАх! Этот профайлер рассчитан на тестирование "больших сишных" проектов, а не мелких ассемблерных кусочков. Если прога без релоков, без сишных сорцов, то он толком ничего и не покажет, а так только можно посмотреть какая та или иная ф-ция, сколько заняла тактов. Если в wintest 3-мя проходами тестировать какой-то участок, то получим результат для каждого прохода, а VTUNE покажет примерно тоже кол-во тактов, но в общем (просуммирует все 3 результата), и то, если они много тактов займут, иначе будет упорно предлагать посмотреть в ntoskernel.exe на ф-цию ExReleaseResourceForThread, т.к. там осело большинство тактов тестируемого процесса. Не тестирует он одну-две инструкции ... а я надеялся увидеть как опкода по конвееру и данные по кешу бегают Так что, может стоит скачать AMD CodeAnalist, или под интел не пойдет?
Действительно всё так плохо? От CodeAnalist толку тоже не больше, если нет PDB файла, я пока разобрался как задействовать режим simulation (именно тогда будут квадратики) немало попарился. С MVSC просто, с MASM тоже работает (хотя это не документировано никак).. в общем-то и с FASM можно подружить.. VTUNE наверное хочет экзешник после intel C++ ? надо бы его скачать пощупать, да вот тоже не знаю, пойдёт ли у меня =)
Ну там нашел кучу всяких счетчиков, если их подключить и с пол-часика подождать, то можно увидеть не только общее кол-во тактов, но и такой отчетик: Код (Text): Branch Instructions Retired 37 x 80,909 = 2,993,633 (72.549%) BTB Misses 0 (0%) Clockticks 15 x 667,000 = 10,005,000 (21.127%) Branch Mispredictions Retired 0 (0%) External Bus Cycles - DRDY Asserted (busy) 0 (0%) Data Memory References (all) 25 x 157,486 = 3,937,150 (60.976%) Instructions Decoded 35 x 393,579 = 13,775,265 (64.815%) FP operations retired 0 (0%) L2 Cache Instruction Fetches 0 (0%) Instructions Retired 21 x 667,000 = 14,007,000 (80.769%) L2 M-state Lines Evicted 0 (0%) L2 Cache Requests 0 (0%) Misaligned Data Memory Reference 0 (0%) Micro-Ops Retired 29 x 673,930 = 19,543,970 (70.732%) Resource Related Stalls 1 x 138,559 = 138,559 (0.917%) Partial Stall Cycles 0 (0%) BTB Miss Ratio 0 Branch Instructions Retired Ratio 0.214 Branch Mispredicted per Instruction Retired 0 Branch Misprediction per Branch Retired Instructions 0 Branch Mispredictions per Micro-Op Retired 0 Cycles per Retired Instruction - CPI 0.714 Data Bus Utilization Ratio 0 Fetch Efficiency: Instructions Decoded / Instruction Retired 0.983 Floating Point Ratio 0 Instructions Decoded per Cycle 1.377 L1 D-cache Miss per Instruction Retired 0 L1 I-cache Miss per Instruction Retired 0 L2 Modified Lines Removed Ratio 0 L2 Requests Ratio 0 Misaligned References Ratio 0 Partial Register Stall Ratio 0 Resource Stall Ratio 0.014 UOP Retired per Cycle 1.953 UOPs per Instructions Retired 1.395 Правда потом можно и схлопотать Код (Text): --------------------------- Serious Error --------------------------- A serious error occurred in file D:\VTune5.0\analyzer\src\SVDP\VTSvdp.cpp at line 1524 (Unexpected problem has occured. The Source View window will now be closed.). The failed HRESULT that produced this error is 0x80340003. Please contact technical support. --------------------------- OK --------------------------- Нет, вроде не обязательно, главное чтобы тестируемая прога отбирала много тактов, иначе может посчитать её не достойной внимания Наверное нет, в Requirements перечислены только Intel-камни, не ниже PII
CodeAnalist без PDB файла тоже будет только всякую белиберду выдавать вроде этой, анализ пайпа почему-то делается только если есть source info в этом самом PDB.
Вы же не думаете, что проц способен "запротоколировать" движение каждой микрооперации по пайплайну. На 100% это лишь эмуляция\симуляция под конкретную модель. А в приведенном "отчетике" собрано то, что проц действительно способен мониторить согласно IA-32 (ч.3, глава 15 Debugging and Performance Monitoring). bogrus, а ты кстати в своем wintest пробовал заменить xor+cpuid после тестируемых инструкций на CLD. На P3 получается очень даже хорошо - видно не только как декодирование влияет, но и время исполнения по тактику нарастает при добавлении инструкций. CLD - это вещь, она и декодируется на D0 в начале такта и зависима по флагам.
leo Т.к. VTUNE меня не очень устраивает, то я собираюсь использовать RDTSC, для P4 отрегулировать его не смогу, а под P3 буду попробовать, потом можно комменты вставить, каких-то фич ещё добавить ... Попробовал, тогда у меня такой код показывает 10 тиков Код (Text): add eax,[mem] mov ecx,[mem] inc ecx Хотя с xor+cpuid показывает 1 тик, а с clc+nop+cld показывает 2 тика
leo > Конечно. Причём симуляция реализована самим производителем процессора. Я ещё осмелюсь предположить, что производитель _сначала_ делает программный "макет" процессора, а потом уже переносит его на кремний. Так вот, почему бы ему заодно не использовать части этого самого "макета" при написании профайлера
bogrus Да, действительно если перед CLD стоит инструкция, "сложным" образом воздействующая на флаги, то получаем дполнительную задержку на 4-5 тиков (кроме inc\dec еще и rcr\и т.п., BCD-инструкции и может чего еще). Эту задержку можно убрать если убить зависимость, вставив дополнительно перед CLD элементарную операцию типа xor eax,eax. Хотя вставлять ее на все случаи жизни наверное не стоит, лучше подходить индивидуально - если имеем в конце inc и т.п., то пробуем добавить еще xor и если результат уменьшается на 3-4 тика, значит он ближе к истине.
1bogrus Кеш - это статическая память работает на частоте процессора, если это кеш первого уровня. Следовательно, для чтения данных из кеша достаточно одного перепада напряжения (пол такта), поэтому тест показывает 0, а в случае двух инструкций