Я в шоке. Сравнение компиляторов VC++ и gcc

mama10001

Есть численная программа написанная на С++.
Собираем с помощью Visual C++6.0
Собираем с помощью g++ 3.3.1 (cygwin версия)
Запускаем.
Сравниваем время работы.
Второй вариант работает в 5 раз ! медленнее. Я в недоумении, т.к. такого не может быть.
Вопрос. Как заставить gcc-версию работать с примерно такой же скоростью. В чем здесь может быть дело?

Landstreicher

exception-ы используются? они под cygwin сильно медленные
вообще, чего прога делает хоть бы запостил кусок, который медленно работает

mama10001

Запостить не могу. Там 400Kb.
Exception’ы там отсутствуют как класс =)

Landstreicher

Наверное очень глупый вопрос, но на всякий случай спрошу: какие ключи компилятора используются (у gcc) ?
imho в счетных прогах размером 400 kb как правило есть один цикл размером 4 kb который жрет 99% времени. или в данном случае не так?

mama10001

Цикл такой безусловно есть. Только вызовы, которые из него делаются как раз и составляют в целом почти все 400K
Из ключей используется –O3.
Но мой вопрос также подразумевает, какими ключами это можно исправить, если дело в них?

rosali

Не парься и возьми icc. gcc - действительно плохой компилятор. Он такой популярный, потому что он бесплатный и поддержано много платформ, а вовсе не потому, что он хорошо компилирует.
Если все таки приспичило gcc, то в начале важный вопрос. Алгоритм итерационный?

Julie16

Программа какого рода? В целочисленной арифметике все существующие компиляторы примерно одинаковы. Но вот с плавающей точкой - тут действительно труба.

mama10001

Спасибо за совет про icc, но должен использоваться именно gcc и среда cygwin.
Алгоритм не итерационный. Однако его итерационность не может иметь отношения к делу. Рекурсивные вызовы тоже не по существу, их почти нет.

mama10001

А что там с плавающей точкой?

Marinavo_0507

Я в C++ не понимаю, но слышал, что некоторым помогает -fno-rtti -fno-exceptions.

Julie16

труба

mama10001

про трубу не слышал

спс, попробую позже, сейчас возможности нет

bastii

еще интересно было бы сравнить с версиями посовременней

Landstreicher

Еще можно попробовать -march=<тип_процессора> -finline-limit=<числа от 700 до 2000>

Chupa

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

rosali

Еб! такой трактат написал и не закомитил
вобщем, попробуй привязать к конкретному процессору и использовать какие-нибудь sse там или что у тебя есть (3dnow? или что в AMD с вещественными числами работает?)
man gcc
и там искать
-march=
-mfpmath=

bastii

просто 7.х быстрее чем 6.0

mama10001

Результаты тестирования такие

компилятор | время выполнения (сек)
|
VC | 10
gcc | 69
gcc -O3 | 50
gcc -O3 -fno-rtti -fno-exceptions | 35
gcc -O3 -march=pentium4 | 51

Должен сказать еще, что оптимизация под конкретный процессор бесперспективна вот почему.
1. Программа будет собираться на одной машине, а запускаться на многих, заведомо неизвестно каких.
2. И главное, vc-версия, которую я использовал в этом тесте была собрана на другой машине, так что она явно не оптимизирована под этот проц.

Marinavo_0507

А стандартная библиотека активно используется?
Например, динамическое выделение памяти, в том числе operator new, в том числе неявный?
Кто знает, как в cygwin с этим делом обстоит...

Vladislav177Rus

Стоит заюзать профилировщик

stat7984215

Второй вариант работает в 5 раз ! медленнее. Я в недоумении, т.к. такого не может быть.
Может быть, но конечно не в пять раз, но всё равно gcc медленнее
На rsdn.ru вроде была как-то статья про сравнение компиляторов. Так вот там по скорости математики вроде как раз рулили borland и microsoft, а gcc рулил только в плане loop-unrolling

mama10001

Я точно не знаю. Хотя в выделении памяти тоже может быть дело.
Я вот еще о чем подумал.
Готовая программа использует cygwin1.dll и без нее не работает на сторонней машине.
Может дело в том, что она постоянно выдергивает из нее вызовы и потому так тормозит?
Можно ли как-то ее еще и слинковать с этой dll?

stat7984215

Ты думаешь что это будет сильно быстрее? Ведь вызовы функций (даже из статически слинкованной библиотеки) никуда не денутся. Или я ошибаюсь? cygwin1.dll вроде обеспечивает только реализацию unix-специфичных функций (вроде работы с файлами) под виндой. Может, возможно как-нибудь уменьшить их использование?

psihodog

А что будет, если собрать под каким-нть линухом/БСД на той же машине этот же проект?
(например загрузочный live-cd с FreeBSD заюзать для этой цели)
как вариант заставить тот самый цикл выполняться десять раз подряд (без выполнения всего остального хотя, это хуже, конечно...

voronina

не правильно сравнение если gcc используется cygwinновский, то проги, написанные под MS VS 6.0 надо было запускать под wine
попробуй с этим: http://www.mingw.org/download.shtml
есть еще старые порты: emx(os/2) и rsx.
если интересно, то какие-то версии rar использовали последнюю библиотеку и никто не жаловался на производительность.
З.Ы. другие люди умеют писать производительные приложения, используя код gcc в качестве компилятора, значит нет достаточной подготовки, если не получается. под msvs 6.0, если бы ты последовал рекомендациям и сделал mfc приложение оно бы особо маленьким не было.
З.З.Ы. зря используешь msvs 6.0: intel C compiler и компилятор unmanaged С++ из MSVS .NET 2003 ощутимо быстрее

kira_K

Сам не профессиональный программер, но по собственному опыту могу сказать следующее: расчетная Прога с кучей операций файлового ввода-вывода и с кучей операций с плавающей точкой (среднее время выполнения - 1-2 суток) скомпиленная gcc под Линух в режиме эмуляции Линуха под Фрей работает почти в 2(ДВА!) раза быстрее, чем ее цыгвиновский аналог, скомпилированный той же версией gcc.

evgen5555

скомпиленная gcc под Линух в режиме эмуляции Линуха под Фрей
Одно слово - юнексоиды...

ava3443

Не, это скорее специфика FreeBSD

rosali

под конкретный процессор бесперспективна
Есть такая штука - Blend. Это когда компилятор генерирует варианты для нескольких процессоров, а в самом начале программы стоит cpuid и развилка. Так что и 1. и 2. ничего не значат...
PS. А еще пустись не под cygwin-ом, чтобы за зря gcc не ругать

rosali

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

ava3443

Разные компиляторы по разному следят за точностью вещественных вычислений
Однако, обычно, это "по-разному" документировано и управляется. Как минимум, у IСС/IFC и GCC.

sergey_m

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

sergey_m

Сам не профессиональный программер, но по собственному опыту могу сказать следующее: расчетная Прога с кучей операций файлового ввода-вывода и с кучей операций с плавающей точкой (среднее время выполнения - 1-2 суток) скомпиленная gcc под Линух в режиме эмуляции Линуха под Фрей работает почти в 2(ДВА!) раза быстрее, чем ее цыгвиновский аналог, скомпилированный той же версией gcc.
Наверное речь про dft или taina?
Пока самым приемлемым объяснением описанного тобою факта считается, что libm в FreeBSD побыстрее libm в Linux. А dft мощно юзает всякие математические функции.

sergey_m

> Не, это скорее специфика FreeBSD
Нет, это просто closed source программа с бинарником только под Linux.

rosali

Ну вот ты говоришь компилятору - распараллеливай вещественную арифметику на SSE. Ну он что-то смог на SSE положить, что-то на сопроцессоре оставил из каких-то своих соображений. На сопроцессоре регистры 80 битные, а на SSE 64 битные. Соответственно, при вычислении на SSE точность ниже, чем на сопроцессоре. Ну и что тут может быть задокументировано? Ты предлагаешь, чтобы компилятор про каждое умножение в программе сказал, где он его решил выполнить? И то не поможет...
Если даже и документировано, что с того? Думаешь автор треда прочитал эту документацию? Я просто говорю, что есть такая неочевидная тонкость при измерении скорости работы программ. А ты не знаю чего сказать хочешь, скорее всего ничего.

xronik111

1. Попробовать -mno-cygwin
2. Почитать http://gcc.gnu.org/ml/gcc-help/2003-01/msg00024.html
3. Что касается SSE, в последние пару месяцев поддержку SSE активно улучшали, если не в лом, хорошо бы попробовать собрать последний снапшот gcc-4.0.0.

mama10001

На простейшем примере результаты такие, что показывает,
что узкие места здесь другие, нежели в исходной программе (400K
о которой речь шла выше.

Visual C++6.0
gcc-3.3.1 (cygwin)

compiler | time (sec)
|
VC (release) | 6.529
VC (debug) | 1.221
gcc | 2.914
gcc -O3 -ffast-math | 1.852
gcc -O3 -ffast-math -malign-double | 1.852
gcc -O3 -ffast-math -malign-double -fno-rtti -fno-exceptions | 1.842
gcc -mno-cygwin | 7.281
gcc -O3 -ffast-math -mno-cygwin | 6.529

Мораль: наилучшую скорость дает

gcc -O3 -ffast-math -malign-double -fno-rtti -fno-exceptions | 1.842
При этом отношение скоростей составляет 1.5 в пользу Visual C.
Ключ -mno-cygwin является вредоносным.
Тестовая программа взята с ресурса
http://gcc.gnu.org/ml/gcc-help/2003-01/msg00024.html

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char* argv[])
{
clock_t start, finish;

start = clock;

printf("\nstart...\n");

for (double i = 0; i < 1e6; i++) {
double val = (double)i + 0.01;
val = log(val);
val = exp(val);
val = sin(val);
val = cos(val);
val = tan(val);
val = log10(val);
val = i;
val = sqrt(val);
val = pow(val, 4.567);
}

finish = clock;

double duration = (doublefinish - start) / CLOCKS_PER_SEC;

printf("Elapsed time = %g", duration);

return 0;
}

bastii

а почему VC release работает медленее чем VC debug?

Julie16

Зря ты ветку не дочитал. Там дальше помнится было объяснение почему это плохой тест. Кратко: цикл можно соптимизировать в ничто.

xronik111

Нет желания все-таки попробовать задействовать настройку под процессор (-march, -mfpmath)? При использовании -mno-cygwin попробовать -mhard-float. Убедитесь хотя бы, что плавающая точка выполняется на железе.
Кроме того, проводите тестирование на Вашей программе, а не на искусственном примере. Или хотя бы, как предлагается дальше по ссылке, используйте val1, val2, val3 и складывайте их в конце цикла.
Можно еще попробовать -funroll-all-loops (вроде должно работать с -O3 а также более агрессивный инлайнинг, это регулируется через механизм параметров (--param <name>=<value>).
И все же, попробуйте 4.0.0 пререлиз. Я не знаю, где его можно взять собранный, но самому собрать несложно, на современном P4 должно быть около получаса.

mama10001

Да, зря (дочитал, но забил ). На правильном примере отношение скоростей стало 1.25, по-прежнему, в пользу Visual C. А release работает быстрее чем debug.

mama10001

Я уже писал, что –march использовался, влияния не оказывает.
-funroll-all-loops также не влияет.
Пробовать 4.0.0 пока не буду, у меня другие задачи

maksimys19

мои результаты:
icl /G6 0.33 s
icl /G6 /QaxK /QxK 0.32
icl /G6 /QaxK /QxK /Qip 0.26
vc 6.0 debug 0.992 s
vc 6.0 release 0.045 s
gcc -O3 -ffast-math -malign-double -fno-rtti -fno-exceptions -m3dnow 1.399
gcc -msse 2.23
[gcc 3.3.1-2]
[icl 7.1]
вывод: - icl с оптимизацией рулит.

bastii

vc 6.0 release 0.045 s
? может 0.45? а то получается быстрее всех

bastii

для полноты картины не хватает теста для VC++ 7.1

maksimys19

сорри
правильно так:
windows
icl /G6 0.033 s
icl /G6 /QaxK /QxK 0.032
icl /G6 /QaxK /QxK /Qip 0.026
vc 6.0 debug 0.992 s
vc 6.0 release 0.045 s
gcc -O3 -ffast-math -malign-double -fno-rtti -fno-exceptions -m3dnow 1.399
gcc -msse 2.23
[gcc cygwin 3.3.1-2]
[icl 7.1]
вывод: - icl с оптимизацией рулит.

maksimys19

linux:
gcc [3.3.2]
gcc 1.09 s
gcc -O3 -ffast-math -malign-double -fno-rtti -fno-exceptions -msse 0.77 s
icc [7.0]
icc 0.01 s

maksimys19

что=то я нафлудил цифрами
живой пример:
когда я спортировал расчетную программу GAMESS под ifc 7.0 под линукс, то скорость возрасла в 2=2.5 раза по сравнению с gcc 3.3.2
Причем, как оказалось, что скорость программы под виндовс и под линукс при одной и той же версии компиляторя ifc примерно одинакова... т.е. разговоры о том, что под линуксом расчетные программы быстрее не оправдались...

rosali

вывод: - icl с оптимизацией рулит.
Быстро у тебя выводы получаются. Люди годами тестовые пакеты составляют, чтобы производительность процессоров/компиляторов исследовать. А ты написал какой-то пример непонятный - и готово, все узнал... Ты хоть результат его работы визуализировать умеешь, а то может в нем ошибка есть? По меньшей мере нужны не отдельные цифры, а _график_, как время работы зависит от объема данных. Когда кеш заканчивается, картина как правило резко меняется, не каждый компилятор способен сгенерировать cache-friendly код. Уже не говоря о том, что надо хотя бы штук 5 различных программ тестовых, в которых локальность по данным разная, разный шаблон обращения к памяти, разное отношение целочисленной и вещественной арифметики и т. п.

maksimys19

Быстро у тебя выводы получаются.
Конечно, я не прав, что делаю столько категоричные выводы.
Но я приводил выше пример с GAMESS. Скорость работы с компиляцией ifl с заточкой под процессор и с IPO была быстрее, чем другие варианты (другие параметры ifl, другие компиляторы cvf или gcc/g77). Плюс по многим тестам, которые есть на iXBT, icl/ifl выигрывал у других компиляторов. Поэтому вообще-то я хотел сказать только одно: ксли есть возможность использовать интеловский компилятор и не хочется тратить время на изучение производительности процессор/компилятор, то в больше чем половине задач это будет оптимальный выбор.
Оставить комментарий
Имя или ник:
Комментарий: