2012-03-13 2 views
3

Я использую Windows7 с использованием CPython для python3.22 и g ++ exGG MinGW для C++ (это означает, что я использую libstdC++ в качестве библиотеки времени исполнения). Я написал две простые программы, чтобы сравнить их скорость.Python быстрее, чем C++? Как это произошло?

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 и std, что замедляет его и заставляет его заняться RAM?
Или это какая-то другая причина?

Edit: Я попробовал еще раз, с \n вместо std::endl и компиляции с -O3 флагом, на этот раз потребовалось 1 мин, чтобы достигнуть 500.000.

+24

Итак, согласно вашему тесту, бесконечный цикл в Python выполняется в два раза быстрее, чем печать одного числа на C++? Это действительно странно. –

+4

Ах, эти образцы кода делают совершенно разные вещи ... Первый не заканчивается. –

+1

Вчерашнее сообщение было опубликовано ... Это домашнее задание из класса или что-то в этом роде? Короткий ответ, буферы C++ на stdout по умолчанию. Python этого не делает. – Swiss

ответ

11

Существует нет ничего здесь очевидна. Поскольку 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; 
} 

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

+2

, так что вы говорите, что C++ работает только медленнее, чем python, потому что python использует самый прямой способ реализации печати и что разница вызвана печатью? Хм ... Думаю, я должен попробовать попробовать без печати. – busukxuan

+5

О, боже, спасибо за помощь .... Я удалил print и cout, а python занял более 10 секунд, чтобы подсчитать до 10^8, а C++ сделал это в одно мгновение (не метафора или гипербола, я имею в виду доля секунды, да, настоящая вспышка). Итак, проблема в cout ... Теперь я узнал отличный урок. Спасибо огромное! – busukxuan

+2

@busukxuan: Написание на консоль всегда будет медленным. Вы пытались перенаправить вывод каждой программы в файл вместо этого?Ваши небольшие программы почти наверняка связаны с вводом-выводом и записью в файл, чтобы исключить медленную запись в консоль. – Blastfurnace

4

std :: endl lags, используйте '\ n', чтобы сделать C++ быстрее.

+0

Я пробовал, примерно то же самое (на несколько секунд медленнее, должен быть случайный разброс) – busukxuan

9

Я думаю, нам нужна дополнительная информация, но я ожидаю, что вы создадите не оптимизированную сборку 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,00 с 0,00 с

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

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

+0

Я попытался снова, с \ n и -O3, на этот раз потребовалось 1 мин, чтобы достичь 500 000 – busukxuan

+0

В этом случае у меня есть только одна теория , Не могли бы вы открыть cmd.exe и проверить их оба в консоли _that_, чтобы убедиться, что это не консоль? Поскольку тайминги _should_ будут почти одинаковыми для Python и C++ для вашего теста. Это связано с тем, что отображение материала на консоли занимает _lot_ времени процессора, которое должно быть идентичным для обоих языков. Петля ничто по сравнению с этим. –

+0

все тот же результат ... T.T Является ли ЦП влиять на результат? Я слышал, что процессоры AMD намного быстрее, когда процессоры Intel медленнее, но могут обрабатывать сразу множество задач – busukxuan

19

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

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

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

  • Вторая проблема менее очевидна, так как она не замечена в коде. Он находится в разработке потоков C++. По умолчанию потоки C++ синхронизируются с потоками C после каждой операции ввода и вывода, так что ваше приложение может смешать 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 раз сказать нам что быстро, и тем, что порядок.

Надеюсь, что поможет вам устранить ваши сомнения. :-)

Смежные вопросы