Скорость SSE с разными оптимизациями: -O1 и -O3

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Сообщение kazalex »

pda писал(а):Чтобы адекватно мерять надо сначала привязывать главный поток к конкректному ядру (если измеряемый код однопоточный), а потом несколько секунд "греть" его, т.е. гонять в цикле какие-нибудь бессмысленные сложения, чтобы частотя ядра на максимум вышла. Иначе не результат, а цена на дрова будет.

Поддерживаю. Только привязывать и греть не обязательно. Достаточно выставить профиль энергосбережения на High performance (Control Panel\Power Options\High performance). У кого AMD Phenom, можно использовать PhenomMsrTweaker - он позволяет переключать профили из трея. Кстати, на ноутбуках тоже можно прифили в трее переключать.
pda писал(а): GetTickCount, вроде тоже может странные показания выдавать, если поток к одному ядру не привязан.

Только не GetTickCount, а QueryPerformanceCounter и только в случае некорректной реализации BIOS (я под VirtualBox'ом периодически ловлю некорректные показания). GetTickCount не рекомендуется для замеров по причине невысокой точности.
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

pda писал(а):У вас тест может показать, что более оптимальный код "работает" медленнее, потому что попал на холодное ядро.


Скорее всего, и в реальных приложениях код будет попадать на холодное ядро и тормозить. Что же это за прога, которую надо "разогревать"?
В любом случае, речь о конкретном наборе оптимизаций.. Я просто учел факт бесполезности выставления ключа О3 и все.
alexey38
долгожитель
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

Сообщение alexey38 »

debi12345 писал(а):Также видно, что умный (на максимальной оптимизации) G++-компилятор "раскусил" что "FasmAdd(P1, P2)" - чистая (зависящая только от входных аргументов) функция и поэтому ее достаточно выполнить один раз, закэшировать результат и потом его использовать в цикле как константу в регистре. FPC таким интеллектом пока еще не обладает.

Собственно Вами показан пример искусственного и сугубо синтетического теста, какими обычно пользуются маркетологи, призывая покупать нечто именно у них, а не у конкурента.
Алгоритмически ни один из приведенных примеров компиляторов не смог соптимизировать задачу, т.к. требовалось всего навсего результат функции вычислить один раз и умножить его на 99999999. Но все же один из компиляторов не стал вычислять некое выражение много раз, а другой тупо выполнил, что ему написали.

К реальности эти примеры не имеют ни какого отношения. Собственно я не вижу большой цены в оптимизаторе заведомо плохого кода. Тут оптимизировать должен программист, а не компилятор.

Составляя тесты, нужно думать головой. Написать хороший (качественный) тест для сравнения оптимизаторов не так уж и легко.
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Сообщение kazalex »

Лекс Айрин писал(а):Скорее всего, и в реальных приложениях код будет попадать на холодное ядро и тормозить. Что же это за прога, которую надо "разогревать"?

В реальных приложениях вероятность "попасть на холодное ядро" есть как у хорошего алгоритма так и у плохого. Вопрос в том, как определить - какой из них хороший, а какой плохой. Так вот, без предварительных мероприятий направленных на уменьшение влияния внешних факторов (как то: активные технологии энергосбережения или повышения производительности, высокая активность фоновых процессов, дисковый кэш ОС) невозможно корректно выявить какой из алгоритмов лучше или хуже. Поэтому бенчмарки писать не так просто, как кажется.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Выкинул из теста выраженеи, которое достсочно вычислить один раз

Код: Выделить всё

A := (((P1 + P2) * P1) / P2) - P1;


FPC ускорился в 2 раза (теперь полсекунды).
G++ разобрался в ситуации лучше и заменил цикл на однократное умножение на лимит цикла - получили мгновенное (0 микросекунд) выполнение.

Меняем цикл на трудный для логической оптимизации (чтобы не избежать цикла и чтобы не было кэширования предыдущего значения)

Код: Выделить всё

for (i=0; i <= 99999999; i++ ) {
  B =  B + A + i;
}

Имеем :
G++ : 0.12 секунды

Код: Выделить всё

****    for (i=0; i <= 99999999; i++ ) {
**** //      A = FasmAdd(P1, P2);
 ****       B =  B + A + i;
  cvtsi2sd   xmm0, rax    # tmp100, i
****    for (i=0; i <= 99999999; i++ ) {
  add   rax, 1    # i,
  cmp   rax, 100000000    # i,
addsd   xmm6, xmm0    # B, tmp100
.LVL8:
****    for (i=0; i <= 99999999; i++ ) {
jne   .L4    #,
****    }

4 команды, из которых 2 - SSE-набор. Все операторы - в регистрах проца.

FPC: 1.14 cекунды

Код: Выделить всё

.Lj21:
   incl   -32(%ebp)
   fldt   U_P$SSETEST_A
   fldt   U_P$SSETEST_B
   faddp   %st,%st(1)
   movl   -32(%ebp),%eax
   movl   %eax,-4(%ebp)
   movl   %eax,-16(%ebp)
   movl   $0,-12(%ebp)
   fildq   -16(%ebp)
   faddp   %st,%st(1)
   fstpt   U_P$SSETEST_B
   cmpl   $99999999,-32(%ebp)
   jb   .Lj21

13 команд, несколько SSE. Часть операндов - не в регистрах а в ОЗУ и возможно кэше проца (что намного тормознее)

Как результат, проигрыш в 10 раз.
Тут либо у FPC оптимизатор должен быть основным направлением совершенования. Либо G++ невероятно умен по этой части :)

попасть на холодное ядро"

Да не в "холоде" там дело, а в оптимизаторе. "-O3" оставляет операнды в регистрах, а "-O1" - в оперативке. Видимо обращение к оперативке быстрее пробуждает проц к 100% активности. Можно кстати удлиннить цикл - это уменьшит эффект от задержки на пробуждние :)
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

kazalex, бейчмарки, как ни пиши, все равно не будут соответствовать реальным приложениям. И да, энергосбережение очень сильно мешается. А как быть в тех случаях, когда нет принципиальной разницы между лучшим и худшим кодом? Ловить микросекунды из принципа?
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Сообщение kazalex »

debi12345 писал(а):Да не в "холоде" там дело, а в оптимизаторе.

Речь не об этом частном случае, а об общем подходе.
Лекс Айрин писал(а):бейчмарки, как ни пиши, все равно не будут соответствовать реальным приложениям.

Это смотря как писать. Если за основу бенчмарка берется ресурсоемкий код реального приложения, то такой тест будет реально отражать положение дел.
Лекс Айрин писал(а):А как быть в тех случаях, когда нет принципиальной разницы между лучшим и худшим кодом? Ловить микросекунды из принципа?

Если нет разницы то и вопросы оптимизации кода/алгоритма обычно не возникают.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

Про мнимые и реальные оптимизации в 10 раз, целительный SSE, и все такое :
http://habrahabr.ru/post/180161/
Программирование*, Алгоритмы*, C++*
По мотивам одного вчерашнего поста про оптимизацию условных переходов при расчете x=sign(a,b)*min(abs(a), abs(b)) якобы в 10 раз. Краткая сводка:

оптимизация налицо, но размер мнимый: не в 10 раз, а 2.5 раза;
бенчмарки надо делать правильно: не надо мерить CPU stalls, RAM bandwidth итп вместо исследуемой функции;
бенчмарки надо делать правильно: иначе могут дико дрожать;
выставлять только приоритет прикольно, но на коротких бенчмарках зря: +0.5% скорости, -15% дрожания;
нужно мерить исследуемую функцию и только ее, только так получаешь корректные данные;
нужно греть проц, нужно считать минимум из N прогонов/секунд, только так побеждаешь дрожание;
нужно пользовать SSE, с ним получилось 8.6 раз, причем код… читается.

В общем, опять пачка классических методологических ошибок при бенчмарке. Кому интересно, как такие ошибки НЕ делать, подробности, детальный разбор полетов, оптимизация в еще несколько раз и, главное, исходники под катом.

Прочитал вчера исходный пост, очень удивился ускорению в 10 раз за счет ликвидации переходов, даром, что на синтетике. Это слишком много, переходы дорогие, но не настолько. Попробовал повторить результаты, посмотрел внимательнее, и натурально: опять детсадовские ошибки в методике бенчмарка! Что же, пора их опять разобрать, пример хороший.


Добавлено спустя 4 минуты 17 секунд:
Также важно чтобы компиятор умел строить SSE4+ инструкции :
На помощь приходит SSE. У меня на десктопе неновый Core2Duo E8500, но даже он умеет SSE4. Разворачиваем цикл в 4 раза, считаем по 4 пары зараз. Прямо в лоб пользуемся специнструкциями для вычисления sign, abs.

1.073 sec, llr() baseline
0.438 sec, llr2() optimized, 2.5x
0.125 sec, llr4() sse + 4x unroll, 8.6x

АФАЙК, FPC пока умеет SSE3-.
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

kazalex,
kazalex писал(а): Если за основу бенчмарка берется ресурсоемкий код реального приложения, то такой тест будет реально отражать положение дел.


Как говорил один профессор, "я всегда найду для вашего калькулятора задачу, которая ему не по зубам". Зачастую, производительность упирается в физические ограничения железа. И в таких случаях хоть оптимизируй, хоть забивай на это дело разница небольшая. ТРот же код может быть так размазан по программе, что его и не выцепишь сразу.
Mirage
энтузиаст
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia
Контактная информация:

Сообщение Mirage »

Нет у FPC SSE оптимизаций. А те что есть для "галочки" чисто.
Надо делать LLVM backend.
А своими силами сделать вменяемую оптимизацию нынче не получится. Это только мануалы к процессорам годы курить надо.
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Сообщение kazalex »

Лекс Айрин писал(а):Зачастую, производительность упирается в физические ограничения железа.

Более того, любая программа, по определению, ограничена возможностями железа. Только это не повод отказываться от оптимизации там, где она приносит ощутимые плоды.
Лекс Айрин писал(а):ТРот же код может быть так размазан по программе, что его и не выцепишь сразу.

Обычно, на этапе декомпозиции задачи становится ясно какие части являются критичными для общей производительности.
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

kazalex писал(а):Только это не повод отказываться от оптимизации там, где она приносит ощутимые плоды.


Там где она дает ощутимые плоды, результат виден на глаз... а это примерно 5-10% повышения производительности (а встречал мнение, что и все 30!) Следовательно, никакая синтетика не нужна. Да и оптимизация должна быть очень качественной.

kazalex писал(а):становится ясно какие части являются критичными для общей производительности.


и стоит ли вообще ее производить. Может случиться так, что весь выигрыш будет съеден накладными расходами.
Аватара пользователя
debi12345
долгожитель
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Сообщение debi12345 »

и стоит ли вообще ее производить. Может случиться так, что весь выигрыш будет съеден накладными расходами.

В случае FPC однозначно стоит (ессно как только она по части SSE когда-нибудь будет допилена в компиляторе) - ведь на кону выигрыш в разы и даже десятки раз.
Аватара пользователя
Лекс Айрин
долгожитель
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград
Контактная информация:

Сообщение Лекс Айрин »

debi12345, я пока не заморачиваюсь с О3 оптимизацией, ограничиваясь предыдущей, ибо разницы в скорости и размере программы не ощущаю. Да и некритична для блокнота скорость. Это с моей колокольни. Сам факт необходимости оптимизации я понимаю. Просто непонятна позиция некоторый к синтетике. Ведь даже при тестировании компов на производительность большую пользу приносят всего 2 теста: Тест архивация файлов (отдельно крупных, отдельно мелких) и гейм тест.
kazalex
постоялец
Сообщения: 296
Зарегистрирован: 01.06.2012 14:54:10

Сообщение kazalex »

Лекс Айрин писал(а):Там где она дает ощутимые плоды, результат виден на глаз...

Вовсе нет. Разницу между 0.75 сек. и 1сек. на глаз не увидишь, но она достаточно велика если говорить о часто используемой функции. Вызовешь такую тысячу раз и отставание в четверть секунды превратится в четыре минуты.
Лекс Айрин писал(а):Следовательно, никакая синтетика не нужна

Синтетика действительно не нужна. Но бенчмаркинг нужен т.к. не всегда предполагаемое совпадает с реальностью. Может оказаться так, что более громоздкий алгоритм работает быстрее.
Лекс Айрин писал(а):Да и оптимизация должна быть очень качественной

Вообще, самый большой выигрышь дают алгоритмические оптимизации и оптимизации основанные на понимании механизмов работы компилятора.
Лекс Айрин писал(а):Просто непонятна позиция некоторый к синтетике

Ты зря называешь бенчмаркинг рабочего кода синтетикой. Синтетика это когда выводы делаются по косвенным характеристикам. Тестирование рабочего кода дает возможность адекватно выбрать правильный путь развития.
Ответить