Автор: Алексей Федорчук
2003 г
Результаты lame-тестов на моей машине так заинтриговали меня, что немедленно по размещении итогов предыдущего тура к месту дислокации машины на Athlon-XP/1800+, конфигурация которого была описана в статье о первом туре. И повторил — к сожалению, до того, как ознакомился с соображениями Георгия Шаповалова в нашем форуме, описанными в предыдущей статье. Картина получилась довольно показательная.
Итак, на этой машине имелся Red Hat 9, уцелевший после 1-го тура, содержащий в себе ядро 2.4.20 и gcc
3.2.2. На этом хозяйстве был последовательно собран lame
с теми же настройками, что и на моей: уровни оптимизации -O0
, -O1
, -O2
без всяких дополнительных флагов, сборка lame
по умолчанию — напомню, она выполняется с флагами
CFLAGS="-O3 -fomit-frame-pointer -ffast-math -funroll-loops -Wall -pipe"
сборка с флагами
CFLAGS="-O3 -march=i686"
и две сборки конкретно под Athlon-XP. В первой задействовался стандартный сопроцессор:
CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -funroll-loops -pipe -mfpmath=387"
Во второй — флаги для мультимедиа-инструкций:
CFLAGS="-O3 -march=athlon-xp -fomit-frame-pointer -funroll-loops -pipe -mfpmath=sse -mmmx -msse -m3dnow"
В связи с замечанием Георгия скажу пару слов о том, откуда взялся флаг -funroll-loops
. Происхождение его — чисто эмпирическое, в цикле статей о тестировании процессоров на
Как и ранее, после каждой сборки lame
трижды выполнялось конвертирование WAV -> MPEG все того же 750-мегабайтного файла (исключение — для сборки при -O0
, причину вы легко поймете, взглянув на таблицу). Как и в первый раз, результаты по lame продемонстрировали просто потрясающую воспроизводимость — в каждой серии отличий более чем на секунду не отмечалось — что в CPU time, что в Real time. Зато здесь я впервые заметил разницу между CPU time и Real time: первое было меньше стабильно на 2-3 секунды. Поскольку результаты по CPU time показали суммарно лучшую воспроизводимость, в таблице и на диаграммах использованы именно они (напомню, что в первом lame-тесте оба показателя были просто идентичны).
Вот, собственно, и все о тестах — далее предлагаю обратиться к таблице (по указанной выше причине я решил ограничиться только сравнением «средних» значений) и диаграмме.
Таблица. Сравнение средних | |
-O0 | 00:13:55 |
-O1 | 00:05:07 |
-O2 | 00:05:01 |
Default -O3 | 00:04:57 |
-O3 -march=i686 | 00:04:28 |
-O3 -march=athlon-xp/387 | 00:04:28 |
-O3 -march=athlon-xp/sse | 00:04:32 |
Имеющий глаза все увидит сам, но не откажу себе в удовольствии кратко описать картину:
- резкое повышение быстродействия при применении хоть какой-то оптимизации — разница между
-O0
и-O1
— более чем в два с половиной раза; - едва, но все же заметный, рост производительности от
-O1
до-O3
чистого; - ощутимый прирост скорости при переходе к
-O3 -march=i686
, составивший почти полминуты; - абсолютно совпадающий с ним результат для
-O3 -march=athlon-xp
с задействованием 387;
и, опять же, чуть видимое, но все же — видимое, падение при переходе к сочетанию -march=athlon-xp
с наборами sse-типа.
То есть качественно картина практически аналогична полученной для Pentium-4, за исключением отдельных деталей. Так, быстрый сопроцессор Athlon’а помешал, видимо, флагу -funroll-loops
отъесть у него производительности. Большие абсолютные значения времени кодирования (все же реально здесь было на один гигагерц меньше, чем на моем агрегате) выявили чуть заметные отличия при уровнях оптимизации -O1
, -O2
и -O3
. И инструкции sse-типа повредили Athlon’у не так сильно, как «четверке» :-)). Однако все остальное вполне укладывается в наметившуюся ранее тенденцию. Что позволяет сделать уже более определенные выводы.
Помните, как Атос во время завтрака при возвращении в Париж (после истории с подвесками) спросил своих товарищей, что они едят? И когда в ответ те начали расписывать изыски французской кулинарии, возразил: «Господа, вы едите конину. Может быть, даже с седлом».
Так вот, господа, сидящие за крутейшими «четверками» и Athlon’ами и воображащие себя пожирателями трюфелей и омаров (не обижайтесь, это я и про себя). Вы работаете за PentiumPro. Может быть, даже без инструкций mmx/sse
… И отсюда — первый вывод: единственные флаги оптимизации, в общем случае окупающие усилия пальцев по их вводу и амортизацию клавиатуры — это
CFLAGS="-O3 -march=i686"
А все остальное, включая mmmx/msse/msse2, способно в лучшем случае не очень ухудшить быстродействие.
Отдельно — о флагах из области mmx/sse. Теоретически они должны бы дать прирост быстродействия. Однако для этого, как резонно заметил Георгий, собираемая с ними программа должна знать о существовании таких инструкций. А похоже, что большинство программ (даже таких, как lame
, которой они могли бы принести пользу — чему примером виндовые аналоги) об этом и не подозревают.
И — к слову сказать, правильно делают. Мне всегда казалось, что подмена универсальных инструкций специализированными если и даст сиюминутную выгоду, в долгосрочной перспективе не оправдана: а как завтра Intel выдумает новый набор, mega-sse#? Тогда как старый добрый сопроцессор — он и в Африке сопроцессор…
Второй вывод: пример lame
убеждает, что есть программы, не оптимизируемые под процессор (или процессоры, под которые некоторые программы оптимизировать бессмысленно?). Однако мы знаем примеры и противного: ведь те 30 процентов для gcc
, полученные таким образом
Остается определить, для каких программ жесткая оптимизация оправданна, а для каких — может даже и повредить. Решать эту проблему я предлагаю методом общенародного супермегатестирования. Для чего отнюдь не требуется где-то собираться и чего-то всем миром мучать. Достаточно, если каждый заинтересованный пришлет результаты измерений по какой-либо важной для него (или просто любимой) софтине — при сборке по умолчанию и при компиляции с различными флагами. Из чего со временем и составится общедоступная база данных оптимизируемых программ (или — не оптимизируемых, помните, что в данном случае отрицательный результат — тоже результат).