Я пользовался старым (v 2.?) Ещё в эпоху простых пней. Там удобней было ляпы находить по параллелизации U/V. А новый как то поставил - он мне систему обрушил, такая тормозень этот новый VTUNE! Его на бейсике писали похоже причём тяп/ляп. Но по твоему вопросу беспокоится нечего - он идёт с тучей док включая и тюторы. Я кстати от него только доку и оставил - там второй том (инструкции) от Intel сделан в chm. В chm как то удобней - можно программировать поиск через API, вот единственное что полезного я там для себя нашёл. У Касперски (Крыса) в книжке тоже рассказы про VTUNE, он то ли некоторые главы то ли вообще здоровый кусок книжки и на русском и на английском где то выложил для публичного пользования. Спроси у него.
Я против переписывания с языка высокого уровня на ассемблер только ради факта, что ассемблер теоретически быстрее. Но, я даже очень за оптимизацию кода, который часто вызывается.
Тогда еще один аспект. Не проблема написать на ассемблере программы для матричной алгебры, проблема оттестировать их, чтобы можно дать рядовому юзеру. Вот поэтому и приходится лавировать между старыми проверенными фортранными текстами и коммерческими оптимизированными библиотеками. То же самое касается алгоритмов оптимизации используемых в компиляторе. Гений конечно придумает, но во сколько обойдется проверка его идеи ?!
Не вижу проблемы в тестировании... 1. Пишем библиотеку функций на ассемблере для матричных операций 2. Пишем тестовый контейнер: програмку, которая читает из файла матрицы+результат, вызываем библиотеку и сравниваем с результатами. Всё автоматизировано, только надо придумать и написать входные файлы, а ещё лучше использовать ФОРТРАН для генерации такого файла.
Мы движемся по одному кругу фраза "старыми проверенными фортранными текстами" говорит, что кто-то их писал, значит проблемы были уже преодолены в прошлом, и преодолены людьми. Мы должны либо сказать что "мы не люди такого" сорта либо, что "ничего нового написать без страшных потерь невозможно", что противоречит действительности так новые библиотеки постоянно выходят. Это просто проблема своего позиционирования в мире программирования, т.е. психология, никаких практических вещей связанных с математикой или прикладным кодированием в ней нет. Если главная задача кодёра - быстрые решения по документообороту в его конторе, разумеется заставлять его писать серьёзное мат обеспечение покажется ему "слишком". Другое дело если человек заранее готовит себя как системщик, то готовность и психологическая и проффессиональная приходят со временем. Дело в том, что большинство системщиков ушло и уходит в ЯВУ как основной инструмент (долгая и пережёванная неоднократно тема) поэтому любители и новички просто мало видят примеров серьёзной работы и из-за этого появляется психологический момент - иллюзия, что это как-то с ассемблером связано. На самом деле связано с людьми, так сложности языка слабосравнимы с реальными профессиональными трудностями - это правильная мат модель в сложных проектах. Это как разница между десантником (начну а там поглядим) и полководцем где метод тыка дорого стоит и нужно уметь моделировать в голове (или схемах) сложные композиции. Мой личный пример не эталон но сгодится как пример, даже в небольших проектах у меня уходит где то 95 процентов на обдумывание общей модели и лишь процентов 5 на непосредственное кодирование в редакторе. Эти 95 процентов не зависят от того на чём я буду писать - я придумываю тех. описание задачи, поиском в ней связей и подводных камней как если бы у меня был робот который мог бы закодировать за меня эту задачу, от меня в данный момент требуется лишь очень точно её смоделировать. А потом на 5 процентов времени я уже сам становлюсь этим "роботом" и кодирую.
emergenter Дизассемблируй программу, собранную интеловским компилятором и использующую интеловские библиотеки и поймёшь, что она состоит из коротких многочисленных процедур, что, конечно, удобно, но если взять во внимание большие циклы, то,естественно, возникают потери.
lis > Утверждение IMHO весьма спорное, intel C++ очень агрессивно inline'ит функции (даже те, которые не объявлены как inline ). собственно, это и есть один из способов оптимизации по скорости. Вообще, немного странный компилятор. Любит выравнивать функции по 4х байтной границе, что не совсем понятно. В случаях, когда разумно использовать word-половину регистра, зачем-то копирует посредством MOVZX в другой и потом работает уже с ним (что ведёт к увеличению кол-ва команд и размера кода). Похоже, он совсем не умеет использовать партиальные регистры, во всяком случае, мне так и не удалось заставить его это делать. При многократном вызове API функции не сохраняет адрес в регистре с последующим call reg32. Что-то ещё было, забыл :-( MSVC, например, прекрасно со всем этим справляется, и, в общем случае, лучше оптимизирует по размеру. (правда он плохо понимает inline, приходится писАть __forceinline) Причем он бесплатный, чего не скажешь про intel :-(
MSVC (по крайней мере 13.10) выравнивает точки входа в функции по границе 16 байт (если указано /Ot) Выравнивание по 4 я не видел. Ещё довольно часто не делает inline даже такие методы классов: Код (Text): class foo { void inline method {...}; }; > "Скорее" - "не скорее" -- это не критерии В общем, можно принять такую теорию: более компактный код лучше для декодера и кэша. А в частных случаях речь идёт о количестве операций. Вот пример компиляции одного и того же кода: Код (Text): ; MSVC 33DB xor ebx, ebx ................... 66:395D 10 cmp [ebp+10], bx 75 09 jnz 004024A7 ; intel C++ compiler 0FB75424 38 movzx edx, [word esp+38] 85D2 test edx, edx 75 14 jnz 00401900 Что будет выполняться быстрее думаю очевидно. Да это ещё что бывает и так: Код (Text): 0FB7C3 movzx eax, bx 85C0 test eax, eax 75 10 jnz 00401958 Вообще, я плохо понимаю смысл оптимизировать по скорости message loop
S_T_A_S_ Насчет partial registers, MOVZX и CALL reg32 (indirect calls) есть соответсвующие рулы в IA-32 Optimization и было бы странно, если бы Intel compiler их не придерживался. Предпочтительное использование test r,r вместо cmp m, i/r при сравнениях jz\jnz тоже описано (правила 50 и 51, раздел Compares). > "Что будет выполняться быстрее думаю очевидно" ?
Ok. Посмотрим, что там за правила скрываются за голыми цифрами: (IA-32 Intel® Architecture Optimization Reference Manual - 24896611.pdf. К слову, в книжке 248966-009 номера были другие) Речь идёт о сравнении посредством cmp с нулём, а не с другим регистром (если уж лезть в теорию, то сравнение регистра с самим собой может оказаться медленнее, т.к. количество портов чтения из регистра ограниченно) Это вообще непонятно как увязать с кодом который я привёл выше :-? > Было бы не плохо эти разделы указать, а то я на вскидку могу вспомнить только об indirect branch с вычисляемым адресом. Чем отличается call reg от call [mem] ? 2й вариант это не indirect ??? Более того, при 2м варианте вызова API есть вероятность, что адрес "уйдёт" из кэша и при повторном вызове будут задержки. Если же адрес в регистре, то регистр будет сохранён в стэке в прологе функции, а при выходе из неё восстановлен. А стэк всё всремя в кэше. Размер - + 2 байта на первый вызов, но каждый последующий - 4. Насчет partial registers, MOVZX уж не имеется ли ввиду это: Тогда читаем дальше: Или может это: Мои замеры показывают, что (на Athlon) cmp [ebp+10], bx выполдняется столько же, что и cmp [ebp+10], ebx Если же добавить лишнюю инструкцию, то для меня очевидно, что это будет медленнее
> "Если же добавить лишнюю инструкцию, то для меня очевидно, что это будет медленнее" Во-первых, в сравниваемых примерах число инструкций одинаково xor+cmp и movzx+test. Во-вторых, и в P6 family и в NetBurst (да наверняка и в K6,K7) бОльшую роль играет не число инструкций, а число микроопераций. В данном случае cmp m,r это 2 моп, а xor,movzx,test по 1. Поэтому в первом варианте имеем 3 моп, а во втором 2. Более того на P6 family одно-моповые инструкции могут декодироваться по 3 шт.за такт, а состоящие более чем из 1 мопа, декодируются только на декодере D0 в начале цикла => возможна доп.задержка на декодирование cmp m,r если она не "впишется" в последовательность 4-1-1. PS: Странное дело подозревать в "тупости" компилятор от производителя процессора - уж кому как не Intel лучше знать, что будет "лучше" на их камнях. Если речь об оптимизации под атлоны, то другое дело, тогда можно и посомневаться в "премудрости" Intel compiler.
leo > Разве оно одинаково? MSVC обнуляет ebx совершенно в другом месте, и далее использует этот регистр как константу = 0 во множестве операций. (этот регистр не изменяется в stdcall, cdecl & fastcall конвенциях) > Не надо путать грешное с праведным - те одноµop'овые movzx и test имеют зависимость по данным, и не могут выполняться параллельно, так что имеем те же 2 µop при большем размере. А на PIV вообще один декодер, не стОит про это забывать! И, кстати, если данные signed, то используется movSx, которая не очень то и быстрая на PIV. > Я где нибудь говорил что-то подобное? Хороший компилятор, не какой-нибудь борланд, только стОит дорого. Для каких-то целей, возможно, и лучший, а изначально речь шла о размере кода vs MSVC. Хотя, AFAIK, Intel имеет к этому компилеру такое же отношение, как Microsoft к Connectix, ой тфу, Microsoft Virtual PC А, врообще, логика конечно железная. Intel'у лучше знать, поэтому не верьте своим глазам =) movzx eax, bx test eax, eax или test bx, bx
S_T_A_S_ Привет! А как ты собирал программы в VC? Подключал интеловский компилятор? Если нет, то какую версию VC использовал? У меня 6-я, там посто так P4 не поддерживается.
> "Intel'у лучше знать, поэтому не верьте своим глазам" Защищать или оправдывать Intel я не собираюсь. Может они и в самом деле тупо следуют своим правилам - не берусь судить и тем более выносить приговор. А вот глазам своим не всегда следует верить (особенно если глазки устали от длительного изучения архитектуры 8086 . С размером кода и декодированием в примере с test bx,bx против movzx конечно все ясно. А вот по скорости выполнения на PIV эти варианты практически не различимы, хотя кому-то может и "очевидно", что "две" инструкции должны выполняться дольше чем "одна". Если бы еще точно знать, что скрывается за этой "одной" инструкцией...
lis > Ты наверное Visual Studio (VS) имеешь ввиду? у меня нет её. В качестве IDE я использую другие проги. Компилятор от микрософта (VC 13.10) давно доступен бесплатно с их сайта, тот что в 6й студии imho уже не актуален. ICC используется так же как и VC, только меняем cl.exe на icl.exe Однако, если сорцы компилируются VC, не факт, что интел их переварит - он более строгий к синтаксису и отклонениям от стандарта. leo Ну опять ты абстракции какие-то говоришь, что значит ? Секундомером не измеришь что ли Если декодер один, то он сначала декодирует одну команду, а потом (!) другую.
S_T_A_S_ Под выполнением я имел ввиду собственно execution без учета декодирования, т.е. в предположении что мопы поступают из trace-кэша (повторное исполнение тела цикла или процедуры). Wintest от Агнера-bogrus'a показывает одинаковые результаты для циклов с test bx,bx и movz+test. Это можно как-то объяснить распараллеливанием (с "соседними" инструкциями), но можно и предположить, что test r16 все таки выполняется дольше чем test r32, скажем 1 такт против 0.5+0.5=1. Должна же тут быть какая-то логика, почему Intel так упорно избегает partial registers.
lis Ну да, я под vc понимаю компилятор, а ты - оболочку Ничего никуда не интегрировал, компилирую так: icl source.cpp leo Я всё не пойму, как научиться мерять время выполнения одной инструкции? И почему можно пренебрегать временем декодирования? А временем чтения инструкций из памяти? Может, проц сразу с винта читает в trace cache? > Да им влом лишний модуль в компилятроре писать