Как стать автором
Обновить

Оптимизируем код, или перегоним Огнелиса в скорости

Время на прочтение2 мин
Количество просмотров694
Почитал топик об новых супероптимизациях в Огнелисе и долго думал.
Для меня не очень понятно, почему вокруг такого рода работы устроен праздник с феерверком и снегурочкой. Давайте подробнее рассмотрим что же было сделано.

* Function Inlining: Removing the overhead of function calls by simply replacing them with their resulting native code.
Инлайнинг функций умеют делать практически все компиляторы. Это очень простой и можно сказать бесплатный способ ускорения программы. У него есть определенные ограничения:
1) Избыточный инланинг ведет к раздуванию кода. Это сейчас практически не проблема — памяти ощутимо много, но компилятор имеет ограничение сверху на размер включаемой ф-ции.
2) Компилятор НЕ умеет инлайнить функции из соседнего модуля, из системных библиотек, а так из динамических библиотек.

Кроме того нормальный (современный) компилятор умеет работать с так называемыми «интринсиками» — функциями, которые он распознает по табличке и имеет готовый код для них. Это обычно математические функции, такие как sin(). Так вот, этот самый синус будет сделан не как call sin(), а будет вставлен куском кода, т.е. автоматически заинлайнен.

* Type Inference: Removing checks surrounding common operators (like «+») when the types contained within a variable are already known. This means that the engine will have already pre-determined, for example, that two strings need to be concated when it sees the «+» operator.

Ну эт обычно называется RTTI skip — выбросили проверку типов там где она не нужна… Возможно для JIT компилятора это и суперкруто, однако обычные умеют делать такое уже давно. Естественно вся ответственность за типы, а точнее их возможное несоответствие ложится на программиста :)

* Looping: The overhead of looping has been grossly diminished. It's one of the most common areas of overhead in JavaScript applications (common repetition of a task) and the constant determining of bounds and the resulting inner code is made negligible.
9 из 10 что был сделан простой анролл цикла. Unrolling представляет собой дублирование тела цикла N раз:
for (int i=0; i<maxI; i++){
a[i] = b[i]+c[i];
}


если unroll на 4 то получаем:
for (int i=0; i<maxI; i+=4){
a[i] = b[i]+c[i];
a[i+1] = b[i+1]+c[i+1];
a[i+2] = b[i+2]+c[i+2];
a[i+3] = b[i+3]+c[i+3];
}

Ну и плюс доппроверку, что maxI кратно 4 :)

Теперь берем нашу программу, Intel C Compiler (или Intel Fortran Compiler — кому что нравится) и собираем проект со следующими ключами:
-O3 (да, агрессивная оптимизация);
-axT (включаем векторизацию, т.е использование SSEx + генерация общего кода для тяжелых случаев);
-ip (межпроцедурная оптимизация, включая частичный инлайнинг. для фанатов есть опция -ipo — межмодульная оптимизация, не портабельно!!!);
-ansi-alias -fno-alias (улучшает векторизируемость :) циклов)

Плюс ко всему этому получаем: автоматический анролл циклов как минимум на 4, инлайнинг и интринсики всех математических функций.
И огнелис не догонит ;)
Да, и в общем случае есть разница между обычным и JIT компилятором, но она не настолько велика, чтобы выдавать давно известные фичи за открытия (типа: «О! Мы придумали инлайнинг!»)

PS. Первый блин, просьба комом не бить по лицу.
Теги:
Хабы:
+3
Комментарии13

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн