Python быстрее, чем C ++? Как это произошло?

Я использую Windows7, используя CPython для python3.22 и gGG MinGW. Exe для C ++ (это означает, что я использую libstdc ++ в качестве библиотеки времени исполнения). Я написал две простые программы, чтобы сравнить их скорость.

Python:

x=0 while x!=1000000: x+=1 print(x) 

C ++:

 #include <iostream> int main() { int x = 0; while ( x != 1000000 ) { x++; std::cout << x << std::endl; } return 0; } 

Оба не оптимизированы.

Сначала я запускал c ++, затем я запускал python через интерактивную командную строку, которая намного медленнее, чем прямое начало файла .py.

Однако python опередил c ++ и оказался более чем в два раза быстрее. Python занял 53 секунды, c ++ занял 1 минуту и ​​54 секунды.

Это потому, что у python есть некоторая специальная оптимизация, выполняемая интерпретатору, или это потому, что C ++ должен ссылаться и std, что замедляет его и заставляет его заняться RAM?
Или это какая-то другая причина?

Изменить: я попробовал снова, с \n вместо std::endl и с компиляцией с флагом -O3 , на этот раз потребовалось 1 мин, чтобы достичь 500 000.

Здесь нет ничего очевидного. Поскольку Python написан на C, он должен использовать что-то вроде printf для реализации print . Потоки ввода-вывода C ++, такие как cout , обычно реализуются способом, который намного медленнее, чем printf . Если вы хотите поставить C ++ на более высокий уровень, вы можете попробовать перейти на:

 #include <cstdio> int main() { int x=0; while(x!=1000000) { ++x; std::printf("%d\n", x); } return 0; } в #include <cstdio> int main() { int x=0; while(x!=1000000) { ++x; std::printf("%d\n", x); } return 0; } 

Я изменил использование ++x вместо x++ . Много лет назад люди думали, что это стоит «оптимизация». У меня случится сердечный приступ, если это изменение повлияет на производительность вашей программы (OTOH, я уверен, что использование std::printf будет иметь огромное значение в производительности выполнения). Вместо этого я сделал изменение просто потому, что вы не обращаете внимания на то, что значение x было до того, как вы его увеличили, поэтому я думаю, что полезно сказать это в коде.

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

Есть две проблемы с исходным кодом на C ++:

  • Он использует std::endl для печати новой строки на каждой итерации. Это очень плохая идея, потому что std::endl делает больше вещей, чем просто печать новой строки – это также заставляет поток очищать накопленный буфер до сих пор; промывка – это дорогостоящая операция, так как она связана с оборудованием – устройством вывода. Итак, первое исправление: если вы хотите распечатать новую строку, просто используйте '\n' .

  • Вторая проблема менее очевидна, так как она не встречается в коде. Он находится в разработке потоков C ++. По умолчанию потоки C ++ синхронизируются с потоками C после каждой операции ввода и вывода, поэтому ваше приложение может без проблем std::scanf std::cout и std::printf и std::cin и std::scanf . Эта функция (да, это функция ) в этом случае не нужна, поэтому мы можем ее отключить, так как она имеет небольшие накладные расходы (это не проблема , это не делает C ++ плохой, это просто цена для функция ). Итак, второе исправление: std::cout::sync_with_stdio(false);

И вот окончательный оптимизированный код:

 #include <iostream> int main() { std::ios_base::sync_with_stdio(false); int x = 0; while ( x != 1000000 ) { ++x; std::cout << x << '\n'; } } 

И скомпилируйте это с помощью флагов -O3 и запустите (и измерьте ) как:

 $ g++ benchmark.cpp -O3 #compilation $ time ./a.out #run //.. real 0m32.175s user 0m0.088s sys 0m0.396s 

И запустите и измерьте код python (опубликовано в вопросе):

 $ time ./benchmark.py //... real 0m35.714s user 0m3.048s sys 0m4.456s 

user и время sys говорят нам, какой из них быстрый, и в каком порядке .

Надеюсь, это поможет вам устранить ваши сомнения. 🙂

Я думаю, нам нужна дополнительная информация, но я ожидаю, что вы создадите не оптимизированную сборку C ++. Попробуйте создать его с помощью флага -O3 . (кто-то, кто знает, что GCC лучше будет иметь больше и лучших рекомендаций). Однако, вот некоторые тайминги из совершенно ненадежного источника: http://ideone.com . Я запускал каждые 5 раз, чтобы получить некоторую меру дисперсии по времени, но только исходный C ++ менялся, и не так много.

Python: http://ideone.com/WBWB9 время: 0.07-0.07s
Ваш C ++: http://ideone.com/tzwQJ время: 0.05-0.06s
Изменено C ++: http://ideone.com/pXJo3 время: 0.00s-0.00s

Что касается того, почему мой C ++ был быстрее вашего, std::endl заставляет C ++ немедленно очистить буфер. '\n' делает новую строку без принудительного сброса буфера, что намного быстрее.

(примечание: я только побежал к 12773, так как ideone.com убивает процессы после того, как они отображают определенный объем вывода, который был самым сервером, который дал бы мне)

std :: endl lags, использование '\ n' сделает c ++ быстрее.

Та же проблема, что и в примере Почему строки чтения из stdin намного медленнее в C ++, чем Python? но в противоположном направлении.

Добавить

std::cout.sync_with_stdio(false);

в верхней части программы