2013-11-15 6 views
2

Существуют различные аргументы, что в некоторых случаях Fortran может быть быстрее, чем C, например, когда дело доходит до сглаживания, и я часто слышал, что он лучше авто- векторизации, чем C (см. here для хорошего обсуждения).эталон простых математических функций: почему Fortran и Julia быстрее, чем C

Однако для простых функций вычисления числа Fibonaci и Mandelbrot на некотором комплексном числе с прямолинейными решениями без каких-либо трюков и дополнительных подсказок/ключевых слов для компилятора я бы ожидал, что они действительно будут выполнять то же самое.

реализация C:

int fib(int n) { 
    return n < 2 ? n : fib(n-1) + fib(n-2); 
} 

int mandel(double complex z) { 
    int maxiter = 80; 
    double complex c = z; 
    for (int n=0; n<maxiter; ++n) { 
     if (cabs(z) > 2.0) { 
      return n; 
     } 
     z = z*z+c; 
    } 
    return maxiter; 
} 

Fortran реализация:

integer, parameter :: dp=kind(0.d0)   ! double precision 

integer recursive function fib(n) result(r) 
integer, intent(in) :: n 
if (n < 2) then 
    r = n 
else 
    r = fib(n-1) + fib(n-2) 
end if 
end function 

integer function mandel(z0) result(r) 
complex(dp), intent(in) :: z0 
complex(dp) :: c, z 
integer :: n, maxiter 
maxiter = 80 
z = z0 
c = z0 
do n = 1, maxiter 
    if (abs(z) > 2) then 
     r = n-1 
     return 
    end if 
    z = z**2 + c 
end do 
r = maxiter 
end function 

Юлия реализация: (. Полный код, включая другие эталонные функции можно найти here)

fib(n) = n < 2 ? n : fib(n-1) + fib(n-2) 

function mandel(z) 
    c = z 
    maxiter = 80 
    for n = 1:maxiter 
     if abs(z) > 2 
      return n-1 
     end 
     z = z^2 + c 
    end 
    return maxiter 
end 

В соответствии с Julia homepage Джулия и Фортран (с -O3) работают лучше, чем C (с -O3) по этим двум функциям.

Как это может быть?

+8

Что показали ваши собственные измерения? –

+0

Где находится 'dp'? –

+0

@HighPerformanceMark: Я не могу воспроизвести. Но это из-за [этого] (http://stackoverflow.com/questions/20001184/static-pre-calculation-optimization-in-clang). – Albert

ответ

7

Честно говоря, я бы не воспринял эти различия слишком серьезно. Различные компиляторы C также дадут разные результаты. Попробуйте запустить микрочипы C с использованием GCC и Clang, и вы получите почти такую ​​же разницу, как C против Fortran. Почему GCC иногда быстрее Clang, а иногда нет? Они просто делают разные оптимизации и генерируют код по-разному. Относительная производительность также отличается от различных аппаратных средств, так как это может зависеть от точного числа регистров, размер кэша, степень суперскалярного пропускной способности, относительной скорости различных инструкций и т.д.

Любопытно, что Fortran является так гораздо быстрее для теста фила, так что, если кто-то отображает это и отправляет ответ здесь, я с радостью буду его продвигать, но разница в ≤ 15% на манделе и других тестах не так уж и примечательна. Самая загадочная вещь для меня в этих тестах - почему Fortran настолько медленен при целых синтаксических разборах. Я подозреваю, что это потому, что этот код делает что-то немым, но я не кодер Fortran, поэтому я не уверен, что нужно улучшить. Если кто-то читает это Fortran pro и хочет взглянуть на this code, было бы весьма полезно. Я подозреваю, что Fortran в 5 раз медленнее, чем C, просто неправильно.

Следует отметить, что при сопоставлении этих результатов теста мы отвергаем времена, равные нулю, чтобы избежать подсчета случаев, когда компилятор просто скомпоновал весь расчет. На некоторых уровнях оптимизации это именно то, что делают как компиляторы C, так и Fortran, и довольно сложно заставить их не делать этого, не используя более низкий уровень оптимизации. Если кто-то хочет выяснить, как заставить компиляторы не постоянно сворачивать эти результаты, все еще полностью оптимизируя контрольный код, это будет приветствуемым вкладом. (Один из возможных подходов состоит в том, чтобы скомпилировать эталонные функции как общую библиотеку, используя полную оптимизацию, а затем связать ее с основной программой с отключенными оптимизациями времени ссылки. Это сложно, но это может сработать.)

В конечном счете, слишком беспокоиться о точном количестве микрообъектов отсутствует большая картина. Суть этих тестов состоит в том, что некоторые языки имеют надежную быструю стандартную реализацию - например, C, Fortran, Julia и Go - в то время как другие языки этого не делают.На медленных языках вам иногда приходится прибегать к использованию другого языка для получения требуемой производительности, в то время как на надежных быстрых языках вам никогда не придется этого делать. Это действительно все. Точная относительная производительность быстрых языков - это гонка вооружений: один язык иногда может двигаться вперед, но другие всегда будут рядом - главное, чтобы они были в гонке вообще.

+0

Новая проблема создана для отслеживания попыток предотвратить постоянную фальцовку на C и Fortran без снижения уровня оптимизации: https://github.com/JuliaLang/julia/issues/4821. – StefanKarpinski

+2

При проверке оптимизированного выхода ассемблера (флаг '-S') функция C занимает около 70 строк, а gfortran использует 115 (я использую 4.4.7, а может быть, некоторые различия)? Похоже, функция 'ichar' является дорогостоящим вызовом. –

+0

Все, что вы говорите, справедливо и для микро-тестов в Юлии, то есть JIT LLVM скомпилировал код Юлии, не так ли? Особенно в случае 'mandel', я не вижу, как компилятор Julia JIT LLVM мог бы сделать что-нибудь более умное, чем компилятор C. – Albert