Насколько лучше на самом деле компиляторы Фортрана?


74

Этот вопрос является продолжением двух обсуждений, недавно появившихся в ответах на " C ++ против Fortran for HPC ". И это больше вызов, чем вопрос ...

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

Поэтому я решил попробовать простой тест: я получил копии daxpy.f и daxpy.c и скомпилировал их с помощью gfortran / gcc.

Теперь daxpy.c - это всего лишь f2c-перевод daxpy.f (автоматически сгенерированный код, безобразный как черт), поэтому я взял этот код и немного его очистил (соответствует daxpy_c), что в основном означало переписать самый внутренний цикл как

for ( i = 0 ; i < n ; i++ )
    dy[i] += da * dx[i];

Наконец, я переписал его (введите daxpy_cvec), используя векторный синтаксис gcc:

#define vector(elcount, type)  __attribute__((vector_size((elcount)*sizeof(type)))) type
vector(2,double) va = { da , da }, *vx, *vy;

vx = (void *)dx; vy = (void *)dy;
for ( i = 0 ; i < (n/2 & ~1) ; i += 2 ) {
    vy[i] += va * vx[i];
    vy[i+1] += va * vx[i+1];
    }
for ( i = n & ~3 ; i < n ; i++ )
    dy[i] += da * dx[i];

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

Все коды были скомпилированы с использованием gfortran / gcc версии 4.5 с флагами "-O3 -Wall -msse2 -march = native -ffast-math -fomit-frame-pointer -malign-double -fstrict-aliasing". На моем ноутбуке (процессор Intel Core i5, M560, 2,67 ГГц) я получил следующий вывод:

pedro@laika:~/work/fvsc$ ./test 1000000 10000
timing 1000000 runs with a vector of length 10000.
daxpy_f took 8156.7 ms.
daxpy_f2c took 10568.1 ms.
daxpy_c took 7912.8 ms.
daxpy_cvec took 5670.8 ms.

Таким образом, исходный код на Фортране занимает чуть больше 8,1 секунды, его автоматический перевод занимает 10,5 секунд, наивная реализация C делает это в 7,9, а явно векторизованный код делает это в 5,6, незначительно меньше.

Это Fortran немного медленнее, чем простая реализация C, и на 50% медленнее, чем векторизованная реализация C.

Итак, вот вопрос: я - нативный программист на C, и поэтому я совершенно уверен, что я хорошо поработал над этим кодом, но последний раз код на Фортране был затронут в 1993 году и поэтому может быть немного устаревшим. Поскольку я не чувствую себя настолько комфортно в кодировании на Фортране, как другие, возможно, кто-то здесь, может ли кто-нибудь сделать лучшую работу, то есть более конкурентоспособную по сравнению с любой из двух версий C?

Кроме того, кто-нибудь может попробовать этот тест с icc / ifort? Синтаксис вектора, вероятно, не будет работать, но мне было бы любопытно посмотреть, как ведет себя наивная C-версия. То же самое касается любого, у кого xlc / xlf валяется.

Я загрузил исходники и Makefile здесь . Чтобы получить точные значения времени, установите CPU_TPS в test.c равным числу Гц на вашем процессоре. Если вы обнаружите какие-либо улучшения в любой из версий, пожалуйста, опубликуйте их здесь!

Обновить:

Я добавил тестовый код Стали к файлам онлайн и дополнил его версией C. Я изменил программы, чтобы сделать 1 000 000 циклов для векторов длиной 10 000, чтобы они соответствовали предыдущему тесту (и поскольку моя машина не могла выделить векторы длиной 1 000 000 000, как в исходном коде Стали код). Так как числа теперь немного меньше, я использовал опцию, -par-threshold:50чтобы компилятор с большей вероятностью распараллеливал. Используется версия icc / ifort 12.1.2 20111128 и результаты следующие

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./icctest_c
3.27user 0.00system 0:03.27elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./icctest_f
3.29user 0.00system 0:03.29elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./icctest_c
4.89user 0.00system 0:02.60elapsed 188%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./icctest_f
4.91user 0.00system 0:02.60elapsed 188%CPU

Таким образом, результаты для всех практических целей одинаковы для версий C и Fortran, и оба кода распараллеливаются автоматически. Обратите внимание, что быстрое время по сравнению с предыдущим тестом связано с использованием арифметики с плавающей запятой одинарной точности!

Обновить:

Хотя мне не очень нравится, куда идет бремя доказательств, я перекодировал пример умножения матриц Стали в C и добавил его в файлы в Интернете . Вот результаты тройного цикла для одного и двух процессоров:

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 2500
 triple do time   3.46421700000000     
3.63user 0.06system 0:03.70elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_c 2500
triple do time 3.431997791385768
3.58user 0.10system 0:03.69elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 2500
 triple do time   5.09631900000000     
5.26user 0.06system 0:02.81elapsed 189%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_c 2500
triple do time 2.298916975280899
4.78user 0.08system 0:02.62elapsed 184%CPU

Обратите внимание, что cpu_timeв Fortran измеряется время процессора, а не время настенных часов, поэтому я обернул вызовы, timeчтобы сравнить их для двух процессоров. Между результатами нет никакой реальной разницы, за исключением того, что версия C работает немного лучше на двух ядрах.

Теперь для matmulкоманды, конечно, только в Фортране, поскольку эта внутренняя функция недоступна в C:

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 2500
 matmul    time   23.6494780000000     
23.80user 0.08system 0:23.91elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 2500
 matmul    time   26.6176640000000     
26.75user 0.10system 0:13.62elapsed 197%CPU

Ух ты. Это абсолютно ужасно. Может кто-нибудь или узнать, что я делаю не так, или объяснить, почему это присущее ему все-таки хорошо?

Я не добавил dgemmвызовы в эталонный тест, поскольку они являются вызовами библиотек для одной и той же функции в Intel MKL.

Для будущих тестов кто-нибудь может предложить пример, который, как известно, медленнее в C, чем в Fortran?

Обновить

Чтобы проверить утверждение Стали о том, что matmulвнутренняя величина «на порядок» быстрее, чем явное матричное произведение для меньших матриц, я модифицировал его собственный код для умножения матриц размером 100x100, используя оба метода, по 10 000 раз каждый. Результаты на одном и двух процессорах следующие:

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=1 time ./mm_test_f 10000 100
 matmul    time   3.61222500000000     
 triple do time   3.54022200000000     
7.15user 0.00system 0:07.16elapsed 99%CPU

pedro@laika:~/work/fvsc$ OMP_NUM_THREADS=2 time ./mm_test_f 10000 100
 matmul    time   4.54428400000000     
 triple do time   4.31626900000000     
8.86user 0.00system 0:04.60elapsed 192%CPU

Обновить

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

Компилятор C сгенерирует тот же компактный код, если эта опция -fcx-limited-rangeустановлена, то есть компилятору дано указание игнорировать потенциальные избыточные / недостаточные потоки в промежуточных значениях. Эта опция каким-то образом установлена ​​по умолчанию в gfortran и может привести к неверным результатам. Принуждение -fno-cx-limited-rangeв гфортране ничего не изменило.

Так что на самом деле это аргумент против использования gfortran для численных расчетов: операции со сложными значениями могут быть чрезмерными / недостаточными, даже если правильные результаты находятся в пределах диапазона с плавающей запятой. Это на самом деле стандарт Фортрана. В gcc или в C99 в целом по умолчанию все делается строго (см. IEEE-754), если не указано иное.

Напоминание: пожалуйста, имейте в виду, что главный вопрос заключался в том, производят ли компиляторы Fortran лучший код, чем компиляторы Си. Здесь не место обсуждать общие достоинства одного языка перед другим. Что меня действительно заинтересовало бы, так это то, что кто-нибудь может найти способ заставить gfortran создать daxpy, столь же эффективный, как в C, с использованием явной векторизации, поскольку это иллюстрирует проблемы необходимости полагаться на компилятор исключительно для оптимизации SIMD, или случай, когда компилятор Фортрана превосходит свой аналог Си.


Одной из проблем синхронизации является то, что если ваш процессор работает в режиме пошагового изменения частоты / турбо, эти результаты могут быть по всей карте.
Билл Барт

1
Ваш daxpy_c.c в настоящее время обновляет x с кратным x и вообще не касается y. Вы можете исправить это, чтобы сделать это справедливым ...
Джек Поулсон

1
@JackPoulson: Хороший улов, исправлены и обновлены результаты.
Педро

2
Кроме того, я совершенно уверен, что разница полностью связана с ручным развертыванием в версии на Фортране, что сбивает с толку компилятор. Когда я заменяю его тем же простым циклом, который вы вставили в свою версию C, производительность между ними почти одинакова. Без изменений версия на Фортране была медленнее с компиляторами Intel.
Джек Полсон

1
@permeakra: На самом деле, стандарт C99 определяет restrictключевое слово, которое точно указывает компилятору: предполагать, что массив не перекрывается с какой-либо другой структурой данных.
Педро

Ответы:


37

Разница в ваших таймингах , кажется, из - за ручное разворачивание единичного-шаг Fortran daxpy . Следующие тайминги на 2,67 ГГц Xeon X5650, с использованием команды

./test 1000000 10000

Компиляторы Intel 11.1

Фортран с ручным развертыванием: 8,7 с
Фортран без ручного развертывания: 5,8 с
C без ручного развертывания: 5,8 с

Компиляторы GNU 4.1.2

Fortran с ручной разверткой: 8,3 с.
Fortran без ручной развертки: 13,5 с.
C без ручной развертки: 13,6 с.
C с векторными атрибутами: 5,8 с.

Компиляторы GNU 4.4.5

Fortran с ручной разверткой: 8,1 с.
Fortran без ручной развертки: 7,4 с.
C без ручной развертки: 8,5 с.
C с векторными атрибутами: 5,8 с.

Выводы

  • Развертывание вручную помогло компиляторам GNU 4.1.2 Fortran в этой архитектуре, но вредит более новой версии (4.4.5) и компилятору Intel Fortran.
  • Компилятор GNU 4.4.5 C намного более конкурентоспособен с Fortran, чем для версии 4.2.1.
  • Векторные свойства позволяют производительности GCC соответствовать компиляторам Intel.

Время проверить более сложные процедуры, такие как dgemv и dgemm?


Спасибо за результаты! Какую версию gcc вы использовали и можете ли вы быть более конкретным в отношении процессора?
Педро

2
Ваш компилятор старше вашего процессора ... Можете ли вы попробовать с gcc-4.5?
Педро

1
Я только что попробовал это. Векторизованная версия с GCC 4.4.5 точно соответствует результатам Intel 11.1.
Джек Полсон

1
Я только что установил gcc / gfortran версии 4.4.5 и не могу воспроизвести различия без развертывания. Фактически, в ассемблере, сгенерированном для обоих случаев, самый внутренний цикл идентичен за исключением используемых имен регистров, которые являются взаимозаменяемыми. Можете ли вы повторить тесты просто для уверенности?
Педро

4
Можем ли мы сказать, что этот вид урегулирования вековых дебатов «мы продолжаем использовать фортран, потому что он более производительный», так что мы, наконец, можем выбросить его в мусорный контейнер?
Стефано Борини

16

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

Работая как на моем ноутбуке (Macbook Pro, Intel Core i7, 2,66 ГГц), относительная производительность вашей версии C с ручной векторизацией и версии Fortran без векторизации зависит от используемого компилятора (с вашими опциями):

Compiler     Fortran time     C time
GCC 4.6.1    5408.5 ms        5424.0 ms
GCC 4.5.3    7889.2 ms        5532.3 ms
GCC 4.4.6    7735.2 ms        5468.7 ms

Таким образом, кажется, что GCC стал лучше векторизовать цикл в ветке 4.6, чем это было раньше.


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


добро пожаловать в scicomp! Я согласен, что версии компилятора так же важны, как и язык в этом случае. Вы имели в виду «вместо» вместо «выкл» в своем последнем предложении?
Арон Ахмадиа

9

Способ написания AXPY на Фортране немного отличается. Это точный перевод математики.

m_blas.f90

 module blas

   interface axpy
     module procedure saxpy,daxpy
   end interface

 contains

   subroutine daxpy(x,y,a)
     implicit none
     real(8) :: x(:),y(:),a
     y=a*x+y
   end subroutine daxpy

   subroutine saxpy(x,y,a)
     implicit none
     real(4) :: x(:),y(:),a
     y=a*x+y
   end subroutine saxpy

 end module blas

Теперь давайте назовем вышеупомянутую подпрограмму в программе.

test.f90

 program main

   use blas
   implicit none

   real(4), allocatable :: x(:),y(:)
   real(4) :: a
   integer :: n

   n=1000000000
   allocate(x(n),y(n))
   x=1.0
   y=2.0
   a=5.0
   call axpy(x,y,a)
   deallocate(x,y)

 end program main

Теперь давайте скомпилируем и запустим его ...

login1$ ifort -fast -parallel m_blas.f90 test.f90
ipo: remark #11000: performing multi-file optimizations
ipo: remark #11005: generating object file /tmp/ipo_iforttdqZSA.o

login1$ export OMP_NUM_THREADS=1
login1$ time ./a.out 
real    0 m 4.697 s
user    0 m 1.972 s
sys     0 m 2.548 s

login1$ export OMP_NUM_THREADS=2
login1$ time ./a.out 
real    0 m 2.657 s
user    0 m 2.060 s
sys     0 m 2.744 s

Обратите внимание, что я не использую никаких циклов или каких-либо явных директив OpenMP . Будет ли это возможно в C (то есть без использования циклов и автопараллелизации)? Я не использую C, поэтому я не знаю.


Автоматическое распараллеливание является функцией компиляторов Intel (как Fortran, так и C), а не языка. Следовательно, эквивалент в C также должен распараллеливаться. Просто из любопытства, как это работает для более умеренного n = 10000?
Педро

3
Это был весь смысл. Автопар проще в Фортране из-за того факта, что Фортран (в отличие от С) поддерживает операции с целыми массивами, такие как matmult, транспонирование и т. Д. Таким образом, оптимизация кода проще для компиляторов Фортрана. GFortran (который вы использовали) не располагает ресурсами разработчика для оптимизации компилятора Fortran, так как в настоящее время он сосредоточен на реализации стандарта Fortran 2003, а не на оптимизации.
Стали

Хм ... Компилятор Intel C / C ++ iccтакже выполняет автоматическое распараллеливание. Я добавил файл icctest.cв другие источники. Можете ли вы скомпилировать его с теми же опциями, которые вы использовали выше, запустить его и сообщить о времени? Мне пришлось добавить оператор printf в мой код, чтобы избежать gcc оптимизации всего. Это просто быстрый взлом, и я надеюсь, что это без ошибок!
Педро

Я скачал последние компиляторы icc / ifort и сам провел тесты. Вопрос был обновлен, чтобы включить эти новые результаты, а именно то, что автовекторизация Intel работает и в Фортране, и в C.
Педро

1
Благодарю. Да, я заметил, что есть небольшая разница, возможно, потому что циклы просты и операции уровня 1 BLAS. Но, как я уже говорил, благодаря способности Fortran выполнять операции с целым массивом и использованию таких ключевых слов, как PURE / ELEMENTAL, больше возможностей для оптимизации компилятора. Как компиляторы используют эту информацию и что она на самом деле делает, это совсем другое. Вы также можете попробовать matmul если вы хотите bpaste.net/show/23035
Staļi

6

Я думаю, не только интересно, как компилятор оптимизирует код для современного оборудования. Особенно между GNU C и GNU Fortran генерация кода может сильно отличаться.

Итак, давайте рассмотрим другой пример, чтобы показать различия между ними.

Используя комплексные числа, компилятор GNU C создает большие издержки для почти базовой арифметической операции над комплексным числом. Компилятор Фортрана дает гораздо лучший код. Давайте посмотрим на следующий небольшой пример на Фортране:

COMPLEX*16 A,B,C
C=A*B

дает (gfortran -g -o complex.fo -c complex.f95; objdump -d -S complex.fo):

C=A*B
  52:   dd 45 e0                fldl   -0x20(%ebp)
  55:   dd 45 e8                fldl   -0x18(%ebp)
  58:   dd 45 d0                fldl   -0x30(%ebp)
  5b:   dd 45 d8                fldl   -0x28(%ebp)
  5e:   d9 c3                   fld    %st(3)
  60:   d8 ca                   fmul   %st(2),%st
  62:   d9 c3                   fld    %st(3)
  64:   d8 ca                   fmul   %st(2),%st
  66:   d9 ca                   fxch   %st(2)
  68:   de cd                   fmulp  %st,%st(5)
  6a:   d9 ca                   fxch   %st(2)
  6c:   de cb                   fmulp  %st,%st(3)
  6e:   de e9                   fsubrp %st,%st(1)
  70:   d9 c9                   fxch   %st(1)
  72:   de c2                   faddp  %st,%st(2)
  74:   dd 5d c0                fstpl  -0x40(%ebp)
  77:   dd 5d c8                fstpl  -0x38(%ebp)

Это 39-байтовый машинный код. Когда мы рассматриваем то же самое в C

 double complex a,b,c; 
 c=a*b; 

и взглянем на вывод (сделанный так же, как и выше), мы получим:

  41:   8d 45 b8                lea    -0x48(%ebp),%eax
  44:   dd 5c 24 1c             fstpl  0x1c(%esp)
  48:   dd 5c 24 14             fstpl  0x14(%esp)
  4c:   dd 5c 24 0c             fstpl  0xc(%esp)
  50:   dd 5c 24 04             fstpl  0x4(%esp)
  54:   89 04 24                mov    %eax,(%esp)
  57:   e8 fc ff ff ff          call   58 <main+0x58>
  5c:   83 ec 04                sub    $0x4,%esp
  5f:   dd 45 b8                fldl   -0x48(%ebp)
  62:   dd 5d c8                fstpl  -0x38(%ebp)
  65:   dd 45 c0                fldl   -0x40(%ebp)
  68:   dd 5d d0                fstpl  -0x30(%ebp)

Это тоже 39-байтовый машинный код, но этап 57 функции относится к выполнению правильной части работы и выполнению требуемой операции. Итак, у нас есть 27-байтовый машинный код для запуска мультиоперации. Эта функция предоставлена ​​muldc3 libgcc_s.soи занимает 1375 байт в машинном коде. Это значительно замедляет код и дает интересный вывод при использовании профилировщика.

Когда мы реализуем приведенные выше примеры BLAS zaxpyи выполняем один и тот же тест, компилятор Fortran должен давать лучшие результаты, чем компилятор C.

(Я использовал GCC 4.4.3 для этого эксперимента, но я заметил это поведение в других версиях GCC.)

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


1
Я просто подготовил пример в соответствии с вашим кодом complex.cи добавил его к коду онлайн. Мне пришлось добавить все входы / выходы, чтобы убедиться, что ничего не оптимизировано. Мне звонят только __muldc3если я не пользуюсь -ffast-math. С помощью -O2 -ffast-mathя получаю 9 строк встроенного ассемблера. Вы можете это подтвердить?
Педро

Я нашел более конкретную причину различия в сгенерированном ассемблере и добавил это к моему вопросу выше.
Педро

Использование -O2 приводит к тому, что компилятор вычисляет все, что возможно во время выполнения, поэтому такие конструкции иногда теряются. Опция -ffast-math не должна использоваться в научных вычислениях, если вы хотите полагаться на результаты.
MK aka Grisu

1
Ну, по этому аргументу (нет -ffast-math) вы не должны использовать Фортран для ваших комплексных вычислений. Как я описываю в обновлении моего вопроса, -ffast-mathили, в более общем смысле, -fcx-limited-rangeвынуждает gcc использовать те же вычисления с ограниченным диапазоном, не соответствующие стандарту IEEE, которые являются стандартными в Fortran. Поэтому, если вам нужен полный диапазон комплексных значений и правильные значения Infs и NaN, вам не следует использовать Fortran ...
Pedro

2
@Pedro: Если вы хотите, чтобы GCC вел себя как GFortran в отношении. сложное умножение и деление, вы должны использовать -fcx-fortran-rules.
Янв

4

Folks,

Я нашел это обсуждение очень интересным, но я был удивлен, увидев, что переупорядочивание циклов в примере с Matmul изменило картину. На моем компьютере нет компилятора Intel, поэтому я использую gfortran, но переписываю циклы в mm_test.f90 для

call cpu_time(start)  
do r=1,runs  
  mat_c=0.0d0  
     do j=1,n  
        do k=1,n  
  do i=1,n  
           mat_c(i,j)=mat_c(i,j)+mat_a(i,k)*mat_b(k,j)  
        end do  
     end do  
  end do  
end do  
call cpu_time(finish)  

поменял весь результат для моей машины.

Предыдущие результаты синхронизации версии были:

#time ./mm_test_f 10000 100
 matmul    time   6.3620000000000001     
 triple do time   21.420999999999999     

тогда как с тройными петлями, переставленными как выше, получаются:

#time ./mm_test_f 10000 100
 matmul    time   6.3929999999999998     
 triple do time   3.9190000000000005    

Это gcc / gfortran 4.7.2 20121109 на процессоре Intel® Core ™ ™ i7-2600K с частотой 3,40 ГГц

Использовались флаги компилятора из файла Makefile, который я получил здесь ...


3
Это не удивительно, поскольку хранение матрицы в памяти благоприятствует одному порядку, т. Е. Если строки хранятся непрерывно, лучше циклически проходить по строкам, находящимся внутри, так как тогда вы можете загрузить каждую строку один раз в быструю локальную память по сравнению с многократной загрузкой (фрагментом ) это для доступа к одному элементу. См. Stackoverflow.com/questions/7395556 .
Кристиан Клэйсон

Я предполагаю, что я был удивлен, что "внутренняя матрима" не была бы закодирована, чтобы делать вещи таким образом. Это значительно быстрее с тройным делом, заказанным вторым способом. Похоже, что он в этом наборе компиляторов, так как более ранние версии gfortran, к которым я могу добраться, были более «плоскими» по времени - неважно, каким образом вы сделали мульт - это заняло почти то же время.
Schatzi

-2

Это не языки, которые заставляют код работать быстрее, хотя они помогают. Компилятор, процессор и операционная система ускоряют выполнение кода. Сравнение языков - просто неправильное, бесполезное и бессмысленное. Это не имеет никакого смысла, потому что вы сравниваете две переменные: язык и компилятор. Если один код работает быстрее, вы не знаете, сколько это язык или сколько это компилятор. Я не понимаю, почему сообщество информатики просто не понимает этого :-(

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.