Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Кто сегодня самый шустрый

Владислав Чистяков
www.optim.ru

Новые участники

Мы протестировали еще три компилятора, а именно: GNU C++ 2.95.3-7 (вернее его порт на Windows - mingw), Borland C++ 5.5 и VC.Net (v 7.0) beta 2.

Компилятор GNU C++ (далее gcc) тестировался нами и в других версиях (меньших чем 2.95.3-7). Причем он каждый раз показывал несколько различающиеся результаты, но так как серьезное отличие оказалось в и без того спорном тесте (подробнее см. в комментарии к этому тесту), я не буду здесь заострять внимание на этой особенности. Gcc на сегодня имеется и версии 3.х, но она не была доступна на платформе Windows на время проведения испытаний. И, так как 2.95.3-7 - это практически бета-версия для 3.х, можно закрыть на это глаза. В будущем мы проверим эти тесты на 3.x и, в случае существенной разницы, опубликуем результаты с нашими комментариями.

Borland C++ 5.5 (далее bcc) - это последняя версия компилятора C++ от фирмы Borland. Это добротный компилятор, довольно точно соответствующий стандарту. Интерес к нему подогревается еще и тем, что Borland C++ 5.5 стал свободно распространяемым.

VC.Net (v 7.0) beta 2 (далее VC7) - это еще бета версия, но его результаты уже позволяют говорить о том, что алгоритмы оптимизации в новой версии заметно улучшились. Не все тесты стали выполняться быстрее, но некоторые (подсчет p , и строковый тест) - несомненно.

Тесты

Итак перейдем к самим тестам.

Вызов метода объекта (Method call)

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов1.44
с разворотом циклов0.37
с "полным" разворотом циклов0.36
Borland C++ 5.5 9.39
VC.Net (v 7.0) beta 2С inline-подстановкой0.00
Без inline-подстановки0.00

Единственный, кто не стал утруждать себя оптимизацией - bcc. Но его результат оказался одним из худших уступив последнее место только явному VB.

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

Gcc прекрасно справился с этим тестом, хотя ни в одном из вариантов не смог полностью соптимизировать весь цикл. По уму, для зачета нужно брать результат, полученный без опций компилятора, заставляющих его раскручивать циклы. Это связано с тем, что цикл в нашем случае - это не зло, а способ заставить компилятор выполнять код достаточное количество раз, чтобы занимаемое процессом время можно было измерить. Учитывая, что компилятор все равно не смог полностью соптимизировать цикл, результаты тестов с раскруткой циклов становятся бесполезными. Однако мы решили оставить его, хотя бы ради справедливости. Так что вы можете сами принять для себя решение, как оценивать gcc.

Еще раз напомним, что не стоит обращать особого внимания на синтетические тесты, ибо выигрыш в данном тесте зачастую достигается не оптимальностью вызова метода, а другими оптимизациями (раскрутка цикла, inline-подстановки...), и тем, что время, затрачиваемое на вызов, относительно невелико. Удивительно то, что это время оказалось на треть больше, чем у Delphi, также продукта этой фирмы. Видимо недаром бытует мнение, что Borland невзлюбил C++.

Вызов виртуального метода объекта (virtual method call)

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов18.78
с разворотом циклов18.67
с "полным" разворотом циклов18.66
Borland C++ 5.5 8.90
VC.Net (v 7.0) beta 2С inline-подстановкой5.77
Без inline-подстановки5.77

VC7 стал победителем этого теста в общем зачете, улучшив время, показанное своим предшественником на 2 сотых секунды :). Такую победу можно было бы и не считать победой, если бы VC7 не показал того же времени в режиме без автоматической inline-подстановки (в этом режиме VC6 показал заметно худший результат, 6.49 секунды, хотя стал в прошлый раз лидером).

Bcc в очередной раз показал время, хотя и немногим, но худшее, чем Delphi. Что же, это некритичное отставание, как это было в случае с VB6, но все равно обидно.

Для gcc этот тест был, пожалуй, наиболее неудачным. Gcc умудрился отстать даже от Java. Причем не помог ему даже вариант компиляции с полной раскруткой циклов - разница в скорости была незначительной (18.78 секунд в обычном режиме и 18.66 в режиме с полной раскруткой циклов). Назвать эту разницу серьезной (особенно на фоне столь серьезного отставания) нельзя. Видимо, повсеместное использование COM, как известно, основанного на виртуальных вызовах, заставило разработчиков традиционных для Windows компиляторов с большим усердием заниматься оптимизацией вызовов виртуальных методов.

Доступ к члену класса

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов4.01
с разворотом циклов0.40
с "полным" разворотом циклов0.40
Borland C++ 5.5 6.79
VC.Net (v 7.0) beta 2С inline-подстановкой1.44
Без inline-подстановки4.33

Результаты данного теста похожи на предыдущий, с той лишь разницей, что VC7 не смог полностью оптимизировать тест в режиме с автоматической inline-подстановкой. Это странно, так как мы видели, что VC7 не задумываясь выбрасывает лишние вызовы и применяет оптимизацию к результатам подстановки. В конце концов, если обращение к члену класса заменить на обращение к глобальной переменной, то VC7 спокойно выбросит цикл, заменив его константным вычислением и подставив его результат в переменную. Короче говоря, Microsoft еще есть над чем работать в следующей версии своего компилятора C++, если таковой планируется.

Gcc продемонстрировал относительно неплохой результат, но все таки отстал от лидера (C#). Как и в прошлый раз, результаты с разворотом цикла приводятся исключительно в целях справедливости и не должны рассматриваться в качестве оцениваемых.

Quick Sort (быстрая сортировка)

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов9.36
с разворотом циклов9.95
с "полным" разворотом циклов9.97
Borland C++ 5.5 10.71
VC.Net (v 7.0) beta 2С inline-подстановкой8.08
Без inline-подстановки8.10

Первый не синтетический тест. Что же он показал? Собственно, показал примерно те же зависимости, которые мы наблюдали в предыдущих тестах. Всс отстал и занял место между Delphi и Java. Gсс был более удачлив, но раскрутка циклов на реальных задачах не дала прироста производительности. Напротив, тест без разворота циклов занял наименьшее время, 9.36, с разворотом циклов - среднее, 9.95, с "полным" разворотом циклов - 9.97, а если включить сразу оба варианта разворотов циклов, то время выполнения теста и вовсе выходит за 10 секунд. Так что данная оптимизация на хороших алгоритмах может дать скорее замедление (хотя и незначительное), чем прирост производительности.

Порадовал только один VC7, который снова смог поднять планку, в этот раз уже на ощутимые полсекунды. Снова повторился прирост не только в режиме с автоматической inline-подстановкой, но и в обычном.

Пузырьковая сортировка

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов5.36
с разворотом циклов4.81
с "полным" разворотом циклов4.81
Borland C++ 5.5 5.05
VC.Net (v 7.0) beta 2С inline-подстановкой5.00
Без inline-подстановки5.00

Это первый тест, в котором опция раскрутки циклов в gcc дала прирост производительности, тем самым позволив gcc занять верхнюю ступень пьедестала почета. Кривизна алгоритма как бы частично компенсировалась разворотом цикла. Однако вариант с "полным" разворотом циклов ничем не отличался от более простого аналога. Время gcc, показанное без оптимизаций раскрутки циклов, оказалось хуже, чем у большинства участников, но тоже очень достойным, подтвердив, что gcc является качественным продуктом. Для сравнения, конечно же, нужно брать результат с раскруткой цикла.

Порадовал в этот раз и bcc. Его результат был хотя и не лучшим, но настолько мало отставал от лидера, что bcc можно поздравить с неплохим результатом.

Подсчет p (целочисленные вычисления)

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов4.10
с разворотом циклов3.80
с "полным" разворотом циклов3.80
Borland C++ 5.5 6.84
VC.Net (v 7.0) beta 2С inline-подстановкой3.77
Без inline-подстановки3.77

В этом тесте VC7 и gcc показали примерно одинаковый результат, практически вдвое лучший, чем у всех конкурентов. Это уже действительно достижение, так как данный тест является совершенно реальным целочисленным расчетом с не очень оптимальным алгоритмом, но все же намного более оправданным, чем (воистину бредовый) алгоритм пузырьковой сортировки.

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

Borland показал достойный результат, но, как всегда, чуть хуже чем у Delphi.

Tree sort

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов12.63
с разворотом циклов12.56
с "полным" разворотом циклов12.71
Borland C++ 5.5 11.54
VC.Net (v 7.0) beta 2С inline-подстановкой11.34
Без inline-подстановки11.37

Удивительно, но трех сотых секунды было достаточно, чтобы пальма первенства ушла из рук Delphi в руки VC7. Не думаю, что поклонники Delphi от этого сильно расстроятся, ведь результат Delphi поистине замечателен, но факт есть факт.

Однако сейчас хочется поговорить немного о другом. Как уже говорилось, в прошлой серии скорость выполнения этого теста в большей степени зависит не от качества компилятора, а от качества реализации хипа. По умолчанию Delphi использует однопоточный режим работы с хипом, и некоторые читатели (с одновременно знакомым и загадочным именем Anonym) усомнились в том, что реализация хипа в Delphi лучше, чем стандартная реализация в W2k. Обосновывалось это тем, что мы не провели тестов в многопоточном режиме. мы решил исправить данное упущение.

Для того, чтобы включить многопоточный режим, мы добавили в обработчик события FormCreate переключение свойства IsMultiThread:

procedure TForm1.FormCreate(Sender: TObject);
begin
    IsMultiThread := True;
end;

Это действительно привело к снижению скорости выполнения теста до 11.51 секунды, но повторное выполнение не привело к какому бы то ни было увеличению времени. А если учесть, что результаты VC6 и Intel C++ были приведены тоже для однопоточного режима, и то, что даже в этом случае Delphi осталась лидером (среди тех участников), то можно сказать, что слова о качестве реализации хипа в Delphi совершенно справедливы. Однако мы не делали тестов на конкурентный доступ к хипу из нескольких потоков, и не можем сказать, как поведут себя конкретные реализации в этом случае. Возможно, в будущем мы проведем такой тест.

Пока можно сказать, что первенство VC7 несколько омрачается тем, что в многопоточном режиме время повторного выполнения этого теста значительно увеличивается. Но, как уже говорилось, это проблема не VC7 как такового, а W2k.

String-тест

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов5.12
с разворотом циклов5.39
с "полным" разворотом циклов5.13
Borland C++ 5.5 15.80
VC.Net (v 7.0) beta 2С inline-подстановкой4.11
Без inline-подстановки4.10

Кое что о этом тесте мы уже сказали. Так что Delphi мы больше трогать не будем. Поговорим лучше об остальных участниках. К сожалению, результаты этого теста нельзя назвать удовлетворительными, так как мы не смогли обеспечить одинаковые условия сравнения даже для C++-компиляторов. Дело в том, что подключение MFC к не Microsoft-овским компиляторам - это непростая задача, на которую попросту не было времени. Особенно это было сложно с gcc. Поэтому мы приняли решение воспользоваться более переносимой реализацией из STL - std::string. Но и тут не все так просто. Существует множество реализаций STL, и наши подопытные (а именно bcc и gcc) использовали разные версии. Причем у bcc оказался самый древний и медленный вариант от HP. Однако результаты теста имеют право на жизнь, так как скорее всего пользоваться программист будет тем, что имеется под рукой.

VC7, как и в других тестах, несколько улучшил свой результат, но до лидеров не достал.

Bcc показал совсем плохой результат, но как уже говорилось, возможно это в большей степени зависит не от качества оптимизации, а от качества реализации STL.

Float-Тест

КомпиляторОпцииВремя (с)
GNU C++ 2.95.3-7 (mingw)Без разворота циклов14.46
с разворотом циклов3.34
с "полным" разворотом циклов3.36
Borland C++ 5.5 15.12
VC.Net (v 7.0) beta 2С inline-подстановкой12.26
Без inline-подстановки12.2

Еще одним тестом, в котором выигрывает не сильнейший, а хитрейший, стал . Так, gcc в обычном режиме показал совершенно посредственный результат, заняв место между Java и VB6. Однако с включенной опцией раскручивания циклов он вдруг сразу переместился на вторую позицию (первым, напомню, был Intel C++). Причем я смог добиться только результата 3.34 секунды, а Юнусов Булат (автор одного из вариантов теста для gcc) добился ~1.5 секунд. Такой результат весьма хорошо выглядит, но совершенно непригоден для сравнения, так как он достигается не за счет увеличения качества оптимизации вычислений с плавающей точкой, а за счет банальной борьбы с циклом. Осознание этого еще больше наталкивает на мысль, что для получения реалистичных результатов нужен осмысленный алгоритм. Причем к этому алгоритму предъявляются довольно строгие требования: он должен в основном состоять из вычислений над переменными типа double, он не должен содержать значительных обращений к массивам (иначе языки, производящие контроль доступа к массивам, будут в заведомо плохих условиях, да и большая часть теста будет мерить скорость доступа к шине памяти).

Если у кого-нибудь на примете есть алгоритм, удовлетворяющий условиям, перечисленным выше, большая просьба связаться с нами по e-mail (tcs@optim.ru), и передать этот алгоритм.

Благодарности

Хочется поблагодарить Александра Корсукова, Булата Юнусова и Игоря Ткачева, помогавших (своим личным трудом и советами) в переносе кода под gcc и bcc.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог