Почему математическая библиотека gcc настолько неэффективна?
когда я портировал некоторый код fortran на c, меня удивило, что большая часть несоответствия времени выполнения между программой fortran, скомпилированной с ifort (компилятор intel fortran) и программой c, скомпилированной с gcc, исходит из оценок тригонометрических функций (sin
, cos
). Это удивило меня, потому что я привык верить, что это ответ объясняет, что такие функции, как синус и косинус, реализованы в микрокоде внутри микропроцессоры.
чтобы более четко определить проблему, я сделал небольшую тестовую программу в fortran
program ftest
implicit none
real(8) :: x
integer :: i
x = 0d0
do i = 1, 10000000
x = cos (2d0 * x)
end do
write (*,*) x
end program ftest
On intel Q6600
процессор и 3.6.9-1-ARCH x86_64 Linux
Я получаю с ifort version 12.1.0
$ ifort -o ftest ftest.f90
$ time ./ftest
-0.211417093282753
real 0m0.280s
user 0m0.273s
sys 0m0.003s
С gcc version 4.7.2
я
$ gfortran -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.148s
user 0m2.090s
sys 0m0.003s
это почти в 10 раз разница! Могу ли я все еще верить, что реализация gcc cos
является оболочкой вокруг реализации микропроцессора аналогичным образом, как это, вероятно, делается в реализация intel? Если это правда, то где горлышко бутылки?
редактировать
согласно комментариям, включенные оптимизации должны улучшить производительность. Мое мнение, что оптимизация не влияет на функции библиотеки ... это не значит, что я не использую их в нетривиальных программах. Однако вот два дополнительных теста (теперь на моем домашнем компьютере intel core2
)
$ gfortran -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.993s
user 0m2.986s
sys 0m0.000s
и
$ gfortran -Ofast -march=native -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m2.967s
user 0m2.960s
sys 0m0.003s
что конкретные оптимизации вы (комментаторы) имели в виду? И как компилятор может использовать многоядерный процессор в этом конкретном примере, где каждая итерация зависит от результата предыдущей?
правка 2
тестовые тесты Даниэля Фишера и Илмари Каронена заставили меня подумать, что проблема может быть связана с конкретной версией gcc (4.7.2) и, возможно, с конкретной его сборкой (Arch x86_64 Linux), которую я использую на своем компьютеры. Поэтому я повторил тест на с debian x86_64 Linux
, gcc version 4.4.5
и ifort version 12.1.0
$ gfortran -O3 -o ftest ftest.f90
$ time ./ftest
0.16184945593939115
real 0m0.272s
user 0m0.268s
sys 0m0.004s
и
$ ifort -O3 -o ftest ftest.f90
$ time ./ftest
-0.211417093282753
real 0m0.178s
user 0m0.176s
sys 0m0.004s
для меня это очень приемлемая разница в производительности, которая никогда не заставит меня задать этот вопрос. Кажется, мне придется спросить об этом на форумах Arch Linux.
тем не менее, объяснение всей истории по-прежнему очень приветствуется.
1 ответов
большинство из этого связано с различиями в математической библиотеке. Некоторые моменты для рассмотрения:
- Да, процессоры x86 с блоком x87 имеют инструкции fsin и fcos. Однако они реализованы в микрокоде, и нет особой причины, почему они должны быть быстрее, чем чистая реализация программного обеспечения.
- GCC не имеет собственной математической библиотеки, а использует предоставленную систему. В Linux это обычно предоставляется glibc.
- 32-бит x86 glibc использует fsin / fcos.
- x86_64 glibc использует программные реализации с использованием блока SSE2. Долгое время это было много медленнее, чем 32-разрядная версия glibc, которая только что использовала инструкции x87. Однако улучшения (несколько недавно) были сделаны, поэтому в зависимости от того, какая версия glibc у вас есть, ситуация может быть не такой плохой, как раньше.
- набор компиляторов Intel благословлен очень быстрой математической библиотекой (libimf). Кроме того, он включает векторизованные трансцендентальные математические функции, которые часто могут дополнительно ускорить циклы с этими функциями.