Почему gccgo медленнее, чем gc в этом конкретном случае?

Я уверен, что все, кто знает golang, знают, что запись в блоге здесь .

Прочитав это снова, я подумал, что использование gccgo вместо go build увеличит скорость еще немного. В моем типичном случае использования (научные вычисления) двоичный файл, сгенерированный gccgo, всегда быстрее, чем двоичный файл, сгенерированный go build.

Итак, просто скачайте этот файл: havlak6.go. и скомпилируйте его:

go build havlak6.go -O havlak6_go
gccgo -o havlak6_gccgo -march=native -Ofast havlak6.go

Сюрприз!

$/usr/bin/time ./havlak6_go
5.45user 0.06system 0:05.54elapsed 99%CPU

$/usr/bin/time ./havlak6_gccgo
11.38user 0.16system 0:11.74elapsed 98%CPU

Мне любопытно, и я хочу знать, почему «оптимизирующий» компилятор производит более медленный код.

Я попытался использовать gprof для gccgo сгенерированного двоичного файла:

gccgo -pg -march=native -Ofast havlak6.go
./a.out
gprof a.out gmon.out

без везения:

Flat profile:

Each sample counts as 0.01 seconds.
 no time accumulated

Как видите, код фактически не был профилирован.

Конечно, я читал это, но, как видите, программа берет 10+ секунд на выполнение... Количество образцов должно быть > 1000.

Я также пробовал:

rm a.out gmon.out
LDFLAGS='-g -pg' gccgo -g -pg -march=native -Ofast havlak6.go
./a.out
gprof

Нет и успеха.

Вы знаете, что случилось? У вас есть идея, почему gccgo со всеми его процедурами оптимизации не может быть быстрее, чем gc в этом случае?

go версия: 1.0.2 gcc версия: 4.7.2

ИЗМЕНИТЬ:

О, совсем забыл упомянуть... Очевидно, я попробовал pprof на двоичном файле, сгенерированном gccgo... Вот top10:

Welcome to pprof!  For help, type 'help'.
(pprof) top10
Total: 1143 samples
    1143 100.0% 100.0%     1143 100.0% 0x00007fbfb04cf1f4
       0   0.0% 100.0%      890  77.9% 0x00007fbfaf81101e
       0   0.0% 100.0%        4   0.3% 0x00007fbfaf8deb64
       0   0.0% 100.0%        1   0.1% 0x00007fbfaf8f2faf
       0   0.0% 100.0%        3   0.3% 0x00007fbfaf8f2fc5
       0   0.0% 100.0%        1   0.1% 0x00007fbfaf8f2fc9
       0   0.0% 100.0%        1   0.1% 0x00007fbfaf8f2fd6
       0   0.0% 100.0%        1   0.1% 0x00007fbfaf8f2fdf
       0   0.0% 100.0%        2   0.2% 0x00007fbfaf8f4a2f
       0   0.0% 100.0%        1   0.1% 0x00007fbfaf8f4a33

И именно поэтому я ищу что-то еще.

EDIT2:

Так как кажется, что кто-то хочет, чтобы мой вопрос был закрыт, я не стал использовать gprof на ровном месте: https://groups.google.com/d/msg/golang-nuts/1xESoT5Xcd0/bpMvxQeJguMJ


person Community    schedule 25.02.2013    source источник
comment
Люди по-прежнему верят в gprof как в канонический профилировщик.. Некоторые моменты: 1) gprof полезен только для программ с привязкой к процессору с мелкими стеками вызовов, без рекурсии, для которых у него есть все символы. 2) Оптимизация компилятора имеет значение только в тесных внутренних циклах или подпрограммах, которые часто вызываются в вашем коде, которые сами по себе не вызывают функции (например, выделение памяти и т. Д.). Оптимизация компилятора не просто ускоряет работу.   -  person Mike Dunlavey    schedule 04.03.2013
comment
Да, я получил это для gprof. И я согласен с вами по поводу оптимизации компилятора. Тем не менее, я бы не ожидал худших результатов от компилятора с возможностью оптимизации. Характеристики должны быть равными или лучше. Если нет, есть возможности для улучшения, и я хотел бы понять, почему :)   -  person    schedule 05.03.2013
comment
Единственное время, которое я когда-либо делал, - это сквозное, возможно, повторяющееся 10 ^ n раз и деленное на это, и я не ищу точности более 3 цифр. Есть шум, и мне все равно. Затем я использую случайную паузу, чтобы найти способы сделать это быстрее. Если это уже не выжато как губка, я найду способы, и тогда я смогу сделать это снова. Когда после нескольких циклов я натыкаюсь на убывающую отдачу, а пк чаще всего оказывается в моих сгенерированных инструкциях, то я включаю оптимизатор, что делает его, может быть, на 10% быстрее. Ууууууууууууууу   -  person Mike Dunlavey    schedule 05.03.2013


Ответы (2)


Запуск сгенерированного gccgo двоичного файла под Valgrind, по-видимому, указывает на то, что gccgo имеет неэффективный распределитель памяти. Это может быть одной из причин, почему gccgo 4.7.2 работает медленнее, чем go 1.0.2. Невозможно запустить двоичный файл, сгенерированный go 1.0.2, под Valgrind, поэтому трудно подтвердить факт, является ли выделение памяти основной проблемой производительности gccgo в этом случае.

person Community    schedule 25.02.2013
comment
Спасибо за упоминание Valgrind. Это самый первый раз, когда я копаюсь в профилировании, и хотя gprof был профилировщиком... я ошибался :) Однако кажется, что Valgrind - это C-only профилировщик/фреймворк профилирования. Он жалуется на неинициализированные значения и, похоже, вообще не работает... Не могли бы вы немного уточнить? - person ; 26.02.2013
comment
Я использовал valgrind --tool=callgrind и KCacheGrind для проверки поведения кода, сгенерированного gccgo. Callgrind от Valgrind также может запускать множество кодов, отличных от C, но, к сожалению, он делает предположения, которые нарушаются двоичными файлами, сгенерированными go1.0.2. code.google.com/p/go/issues/detail?id= 782 - person ; 26.02.2013

Помните, что go build также по умолчанию использует статическое связывание, поэтому для сравнения яблок с яблоками вы должны указать gccgo параметр -static или -static-libgo.

person Ted Kotz    schedule 13.06.2014