Производительность компиляторов С++

На рсдн выложили статью "Производительность компиляторов С++".


Введение

В сети можно найти достаточное количество материалов, посвященных сравнению производительности кода, сгенерированного различными компиляторами С++ на различных аппаратных платформах для определенного сорта тестовых задач (например обзор компилятора gcc 4.0 на сайте coyote gulch). Такие материалы выпускают и производители компиляторов, стараясь привлечь внимание к своим продуктам. Нет никаких сомнений в полезности подобных работ – они позволяют учитывать фактор абсолютной производительности сгенерированного кода при выборе инструмента разработки.

Однако на этапе, когда выбор компилятора уже сделан, перед разработчиком довольно часто встает вопрос о выборе в пользу того или иного подхода к реализации конкретных фрагментов программного обеспечения. Поскольку компиляторы C++ с успехом справляются и с кодом С, то всегда есть выбор – воспользоваться новыми языковыми конструкциями, предлагаемыми C++, или реализовать ту же функциональность средствами C. Другими словами возникает вопрос о накладных расходах, вносимых использованием новых языковых средств, или насколько хорошо реализован соответствующий механизм C++ в конкретном компиляторе.

Сравнений производительности кода на C++ и эквивалентного ему по функциональности кода на C, сгенерированных одним и тем же компилятором, не так много. Хорошо известен фактически только один источник – это Technical Report on C++ Performance комитета WG21. В отчете приведены конкретные результаты и код, на котором производилось сравнение, однако исследуемые компиляторы остаются анонимами. Понять комитет по стандартизации можно, однако практикующим инженерам нужны более точные сведения.

За основу статьи взят материал упомянутого выше отчета. Набор тестов был немного расширен, в некоторых случаях предложенный код модифицирован, а также приведен более подробный анализ возникающих накладных расходов. В большинстве случаев приведены конкретные результаты для конкретных пар компилятор – платформа. В результате читатель сможет получить ответ не только на вопрос «чем я плачу за использование этой языковой конструкции?», но и на вопрос «сколько именно я плачу?».

Заключение

Современные компиляторы C++ демонстрируют высокое качество реализации новых языковых механизмов на всех платформах. Код на C++ практически не проигрывает в производительности функциональному эквиваленту на C, а в некоторых случаях позволяет получить и более высокое быстродействие программ. Досадным исключением остается потоковый ввод-вывод в стиле C++. Однако для этой ситуации есть обходной путь – компилятор C++ справится и с кодом ввода-вывода, написанным в стиле C. Кроме того, всегда остается надежда на разработчиков компиляторов. Библиотека ввода-вывода C++ неизбежно будет становиться эффективнее и эффективнее. А у компиляторов C, учитывая поддержку языком C++ большего количества подходов к проектированию программного обеспечения, будет оставаться все меньше и меньше шансов на использование в сложных проектах.

Критика статьи на форуме рсдн

  • Нет замеров для самого популярного в мире компилятора С++ (Visual C++).
  • Нет замеров для самой популярной в мире ОС (Windows).
  • Нет замеров для второго по популярности в мире процессора AMD x86.
  • Что такое "Intel, 32 бита" не понятно. Толи Pentium 3, толи Pentium 4, толи Pentium Core...
  • Что такое "Intel, 64 бита" совсем не понятно. Толи это семейство x86-64, толи Itanium. Разница колоссальная. Ниже вроде упоминается IA-64 (название десятилетней давности).
  • Sun UltraSPARC-II отстаёт на два семейства от современного Sun UltraSPARC-IV.

А какой компилятор используете вы в своей работе - поделитесь опытом Smile

Последняя правка: пн, 29/08/2011 - 21:59
Submitted by Victor on

Комментарии

c++ использую редко, в основном С.Когда дома то стандартный cl из VS 200x. Или чаще GCC (уж больно много там всяких опций Smile да и бесплатный он)У обоих оптимизация приемлемая, при желании можно "отковырять" cl и писать под него в каком-ниудь постороннем редакторе.

Когда с собой только флешка и я за чужим компьютером то либо Pelles C (производная LCC) но он только для си либо тот же гцц из под какой-нибудь легковесной среды.

Пробовал использовать OpenWatcom но от него так и не добился чего хотел....

Intel использовать не довелось, тем более процессор у меня от AMD.

Быстродействие кода в последнее время сводится к "а догадается ли компилятор развернуть эту хитрую шаблонную структуру в нормальный код", В большнстве случаев догадывается очень хорошо.

Вообще не стоит так сильно гнаться за оптимизацией кода компилятором. Медленные алгоритмы быстрее от этого не становятся.

Submitted by tormoz on
Для "своего" кода -- Intel C++ 9.1, 10.0 как-то не стабилизировался ещё (бываю глюки на максимальной оптимизации); на работе -- MSVC8 для пц и tool-chain на основе GCC 4.2.х для PSP. У визуала, несмотря на заявления мелкософта, до сих пор не фонтан с поддержкой стандарта; иногда очень забавные сообщения комилер выдаёт; GCC впрочем тоже веселит временами :) Watcom был очень клёвый компилер, пока был. Кстати, достаточно опасное заблуждение -- считать что компилер ого-го-го как сам всё зооптимизирует; современные компиляторы далеки от совершенства и часто генерят фигню, если не прилагать дополнительных усилий (речь, ясен пень, о программах сильно сложнее вращающегося куба).
Submitted by BLK Dragon on

>> современные компиляторы далеки от совершенства и часто генерят фигню

Если возможно - приведи примеры.

Submitted by Victor on
Это очень долго и нудно, с асмом (половину которого, PSP, я просто не могу показывать); Навскидку из относительно недавнего -- MSVC8 при std::vector::push_back() обычной структуры утворил конструирование временного объекта, конструирование пустого объекта и копирование одного в другого (на макс оптимизации конечно); интел такого не делал; Есть масса случаев когда компилер в принципе не может оптимизировать некоторые вещи (например случай потенциального aliasing'а входных аргументов что лечится только явным __restrict). Или вот массированное обращение к data-member'у внутри цикла (чтение/ЗАПИСЬ памяти по поинтеру this). Думаете компилер додумается вынести это во временную переменную в регистр? Хрен там. Будет героически читать/писать память, и D-cache не всегда спасает от этого. Продолжать можно бесконечно. Мораль в том чтобы думать и смотреть что происходит в коде (в критических местах в-основном). Собсно, тут в тему будет цитата из одного доклада ипонцев делавших Daxter на PSP; там была табличка как "правильно" и "неправильно". Так вот одна строчка: "code, profile then optimize -- WRONG; design your code to be efficient -- right".
Submitted by BLK Dragon on

в принципе вы правы. (только что кой-чего посмотрел и мое мировозрение перевернулось назад). Но с другой стороны как я уже сказал думать надо... В частности при использовании сложных синтаксических структур особенно шаблонных. Они вообщето сложны не только для "оптимизации" но и просто для разбора. Кстати как показывает практика в 90% случаев более простой код более быстрый Sad

Submitted by tormoz on

Активная запись в члены класса из метода даже в несложных циклах - приводит к почти что 2-кратному падению производительности на синтетическом примере, и вполне измеримой 5-10% разнице на боевом коде.

aliasing также может неплохо влиять на производительность, так что остановимся на нем несколько подробнее.

Цена абстракции (или все, что мама не рассказывала про C++) или глюки компиляторов.

Вопрос в копилку для собеседования на позицию C++ гуру: влияет ли шаблонность метода на видимость переменных?

Цена абстракции-2 (или все, что мама не рассказывала про C++).

Про Prefetch.

магия, чёрная и белая.

Submitted by Victor on

Это не глюки -- просто код не очень эффективный; глюк это когда компилер генерит xor EDX,EDX вместо xor EAX,EAX и всё падает Smile

Из страшных сказок можно вспомнить глюк c инкрементом (именно глюк) GCC 2.9.x на PowerTV; кстати циклы типа текстурирования там выписывались вручную, хоть и на С++.

Да чего далеко ходить, в банальном for( unsigned i=0; i<my_vec.size(); ++i) компилер вынужден вызывать size() каждый раз, ибо в принципе не может знать что нет side-effect'ов; например при обработке гигабайт вершин это может очень даже иметь значение...

Submitted by BLK Dragon on

Ну а все таки, если вернутся к сабжу - какой из ныне существующих С++ компиляторов генерит самый быстрый код с максимальными подстройками под современную архитектуру CPU (там инструкции SSE/3DNow, особенности работы кеша и т.п.) при минимальных вмешательствах программиста? или это еще только мечты?

Submitted by Victor on
А есть выбор? В смысле для пц есть по сути два компилера: MSVC/IC (если за деньги) и GCC (если без денег). Ещё бесплатный вариант MSVC есть. Большинство берёт или визуал за деньги, или визуал без денег -- не о чем разговаривать в-принципе то. А быстрый-быстрый код "при минимальном вмешательстве программиста" компилер ИМХО не будет генерить никогда, всегда придётся соображать что пишешь. Т.е. если хочется поставить галочку в опциях "ускорить не тут всё в надцат раз", то не получится.
Submitted by BLK Dragon on

GameDev.by