Pull to refresh
34
0
Send message
Да, весьма интересно. Начиная с версии компилятора 14.0 (то есть не так уж и давно, точно позднее 2010 года, когда была написана та статья), был изменён диспатчинг. Теперь проверяется не сам процессор, а набор фич, которые процессор поддерживает.
Собственно, подобное и делает gcc, и кэширует часть вычислений. Возможно, что в 18 версии (не Бета) на этом примере мы тоже сделаем подобное, ведь не просто так я копался сидел.
icc делает всё «в лоб», то есть
a0 = fib(43);
a1 = fib(42);
a2 = fib(43);
a3 = fib(44);
a4 = fib(45);
А можно было бы оптимизировать так:
a0 = fib(43);
a1 = fib(42);
a2 = a0
a3 = a2 + a1;
a4 = fib(45);
a4 = a3 + a0
Ну дизассемблер нам не нужен, раз у нас в руках компилятор есть. Можно сразу посмотреть ассемблер. Быстро глянул, и заметил, что в случае с дефолтными опциями оба компилятора генерят примерно одинаковый код для main, вызывая fib. А вот c O3 gcc придумал что-то поинтереснее — он там организовал цикл для вызова fib:
main:
.LFB12:
subq $8, %rsp
.LCFI15:
movl $45, %esi
xorl %r8d, %r8d
.p2align 4,,10
.p2align 3
.L46:
cmpq $1, %rsi
jbe .L47
leaq -2(%rsi), %rdx
xorl %ecx, %ecx
.p2align 4,,10
.p2align 3
.L45:
movq %rdx, %rdi
call fib
subq $1, %rdx
addq %rax, %rcx
cmpq $-1, %rdx
jne .L45
addq $1, %rcx
.L44:
subq $1, %rsi
addq %rcx, %r8
cmpq $-1, %rsi
jne .L46
leaq 1(%r8), %rsi
movl $.LC0, %edi
xorl %eax, %eax
call printf
xorl %eax, %eax
addq $8, %rsp
.LCFI16:
ret

А по дефолту это выглядело так:
main:
.LFB1:
pushq %rbp
.LCFI4:
movq %rsp, %rbp
.LCFI5:
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
movl $47, %edi
call fib
movq %rax, %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
.LCFI6:
ret

В icc похожее на дефолтное у gcc. Нужно взять VTune и посмотреть более детально, могу даже пост про это написать. Но мне думается, что мы просто похуже работаем с рекурсиями, потому что они не очень то востребованы — только в образовательных целях.
Да, с О3 интеловский компилятор уже медленнее. Нужно посмотреть, что делал gcc с O3.
Но опять таки — без векторизации не стоит ожидать чудес от компилятора.
Ну и стоит сказать, что на таких тестах не стоит ожидать большей производительности, векторизации здесь нет.
Только что протестировал:
$ gcc --version
gcc (GCC) 6.2.0
Copyright © 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc test.c
$ time ./a.out
4807526976

real 0m15.512s
user 0m15.465s
sys 0m0.000s

$ icc -V
Intel® C Intel® 64 Compiler for applications running on Intel® 64, Version 17.0.4.196 Build 20170411
Copyright © 1985-2017 Intel Corporation. All rights reserved.

$ icc test.c
$ time ./a.out
4807526976

real 0m10.567s
user 0m10.529s
sys 0m0.000s
Компилятор просто делает ряд оптимизаций лучше, в частности, максимальный прирост даёт векторизация. Если её отключать в нашем компиляторе, то это большой вопрос, будет ли прирост (даже если отключить её для сравнения и в других компиляторах). Векторизатор умеет распознавать достаточно сложные конструкции, и на выходе мы имеем большее число циклов, которые используют регистры по «максимуму», и при этом с использованием последних инструкций. Конечно, и другие оптимизации могут «додавать» производительности, но это ключевая.
Безусловно, у компиляторов Intel есть опции для оптимизации под конкретную микроархитектуру, и здесь мы тоже получим дополнительное преимущество. Тем не менее, возможность сгенерировать код под другие процессоры тоже есть. Возможно, где-то выложены сравнения компиляторов и на других процессорах, мы это не отслеживаем.
В целом, высокая производительность получаемого кода всегда была и остается основным преимуществом Интеловских компиляторов, поэтому сюда и инвестируется много ресурсов/времени.
У gcc есть ряд своих преимуществ, например доступность, открытость кода, поддержка языковых стандартов (появляется чуть раньше, чем у нас).
И ещё одно замечание «вдогонку». В вопросе так же был интерес в самом времени компиляции, а не только выполнении. И вот тут у нас должен быть ощутимый прогресс в 18 версии, поскольку было пофикшено несколько подобных проблем (как в сравнении с gcc, так и с Visual C++, когда мы существенно дольше собирали код).

Но это всегда оборотная сторона медали — если хочешь, чтобы компилятор хорошо (читай как дольше) оптимизировал код, а приложение потом хорошо (читай как быстро) исполнялось — придётся где-то тратить больше времени (или на этапе компиляции, или выполнения).
Пардон за много букв. Более короткий ответ — обычно мы не хуже gcc, а если ваш тест покажет обратное — вам точно нужно связаться с нами, и, очень вероятно, это будет исправлено. В поддержке кроется весомое преимущество.
Да, это конечно важный вопрос. Показывать насколько хорош в плане производительности компилятор принято на общеизвестных тестах/бенчмарках. Так принято в индустрии. Эти тесты могут быть как «идеальными конями в вакууме», так и более сложными, приближенными к реальной жизни (они разные). Для С++ мы часто ориентируемся на SPEC, и в посте про прошлую версию 17.0 я давал данные по производительности на этой бенчмарке:
image
На конкретном железе и с данными версиям компилятора выигрыш был ощутимый (порядка 60% с Microsoft и 50 с GNU).
Для 18 версии данные тоже будут подготовлены позднее и, думается, сравнивать будем уже с 2017 версией.
Но если есть желание понять, какой будет прирост на именно вашем приложении (а это то, что обычно интересует разработчиков, а не цифры про «вакуум»), то имеет смысл просто качнуть тестовую бесплатную версию (для этого она у нас и есть) и посмотреть своими глазами. Обычно, поиграв с опциями из этого поста, можно весьма неплохо разогнаться.

Такого рода опции используются в целях отладки и нахождения ошибок в коде, поэтому их overhead не критичен.
Но посмотреть возможные исключения через fpe0 можно и с release билдом, чтобы убедиться, что компиляторные оптимизации не приводят к проблемам в вычислениях. Для финального билда их нужно отключать.
Да, функциональность растёт, но всё же с windows API или pthreads сложно сравнивать, потому как концепция другая.
Идея отличная, и лично я двумя руками за неё, но пока этого нет. На данный момент есть такие варианты получить лицензию: https://software.intel.com/en-us/qualify-for-free-software
Отмечу, что её можно получить (для Linux) активным участникам Open Source проектов, а так же студентам и преподавателям в образовательных целях (уже без ограничений на ОС).
У Intel несколько поменялась концепция установщика. Теперь доступны не 3 разных версии для скачивания, а можно выбирать компоненты. В результате сгенериться установщик, содержащий только необходимые вам части, который и нужно скачать. Так вот в рамках этой концепции, триал на Professional не очень и нужен. Просто получаем триал на Cluster (он содержит в себе все компоненты Pro), и выбираем что будем качать.
Это не совсем правда. Все библиотеки доступны по Community лицензии здесь. Пакет с Python так же бесплатен, а вот за компиляторы придётся платить денежку. Но имеется большое разнообразие лицензий, в том числе и бесплатных. Так что это всё же не для тех, у кого много денег, а для тех, кто заинтересован в более высокой производительности.
В самом начале поста я рассказываю о том, что входит в Parallel Studio. Это и компиляторы, и библиотеки, различные средства динамического анализа. В целом, «эта штука» для разработчиков, которые заботятся о производительности своего кода.
Я бы не сказал, что компилятор от Интел в плане поддержки стандартов проигрывает. Скажем, тот же С++11 полностью поддерживается у Microsoft только с VS2015, а в Интеловском с прошлой версии 15.0, что даже чуть раньше. На Windows для Интела ориентир в сторону Visual C++, на Линуксе gcc. GNUшному конечно, проигрывает в каких то фичах, но зато OpenMP лучше поддерживает(4.0 раньше всех поддерживался). В целом не всё так однозначно.
Если пробовать новые фичи С++ -то да, будут вылазить проблемы, как и с любым новым кодом — багфикс ещё никто не отменял.
1
23 ...

Information

Rating
Does not participate
Registered
Activity