2

I switched to c++ because i heard its 400 times faster than python, But when i made an infinite loop that increments a variable and prints its value python seems to be faster, How can that be? And how to optimize it?

Python script:

x = 1
while 1:
    print(x)
    x+=1

C++ code:

int x = 1;
while (1) {
cout << x << endl;
x++;
}

I tried optimizing it by putting this command:

ios_base::sync_with_stdio(false);

The speed became almost identical to python's but not faster.

Yeah and i did search for this topic i didn't find anything that explains why.

xMsid
  • 27
  • 2
  • @Ron: no, the explanation is easy. –  Oct 25 '17 at 12:40
  • Friendly reminder that `endl` is virtually always wrong. – Matteo Italia Oct 25 '17 at 12:42
  • @MatteoItalia so i shouldnt be using `endl` then what to use to print a new line? – xMsid Oct 25 '17 at 12:43
  • 3
    @BlueBoy79 `"\n"` - but the key point is that you should not write to the terminal inside your benchmarking loop **at all**. – MB-F Oct 25 '17 at 12:45
  • `"\n" `. `endl` forces a buffer flush, which is useless when printing to console (as in that case IO is line buffered anyway), and kills performance when redirecting to file. – Matteo Italia Oct 25 '17 at 12:45
  • @BlueBoy79 Consider reading about [“std::endl” vs “\n”](https://stackoverflow.com/questions/213907/c-stdendl-vs-n). In short, you should use `std::endl` if you want to end the line (print '\n') AND flush the buffer. – Algirdas Preidžius Oct 25 '17 at 12:46
  • If the purpose of your experiment is to evaluate the relative efficiency of algorithms between two languages, I would find a more objective measure. By the time that everything is done to update the console, any differences in efficiency will be hopelessly buried. – Jon Trauntvein Oct 25 '17 at 13:21

3 Answers3

7

C++'s std::endl flushes the stream, python's print does not. Try using "\n", that should speed up the C++ code.

Doncho Gunchev
  • 2,159
  • 15
  • 21
  • All the three cases (`endl`, `\n` and `print`) flush the buffer if you are writing to console, as OP seem to do. – Matteo Italia Oct 25 '17 at 12:47
  • @MatteoItalia, this is not specified by the standard and is implementation-defined, whereas `std::endl` is – Daniel Trugman Oct 25 '17 at 12:51
  • From my recent tests "\n" does not flush stdout on Linux. Also, when using "\n" in multithreaded application with locks the output still appears in strange pieces (buffering). – Doncho Gunchev Oct 25 '17 at 16:18
4

You are not benchmarking the language, you are benchmarking the OS.

The time it takes to display text (by the windowing system) is longer than the time to prepare the characters (by your code) by orders of magnitude.

You will obtain the same behavior with any language.

  • 5
    In addition to `endl` flushing the buffer of `cout` on every iteration. – Algirdas Preidžius Oct 25 '17 at 12:39
  • So is it my Hardware? – xMsid Oct 25 '17 at 12:41
  • @BlueBoy79: nonsense, both run on the same hardware. Did you understand my answer ? –  Oct 25 '17 at 12:42
  • 1
    @BlueBoy79 I, personally, suspect the core issue is, as I already mentioned, you flushing the buffer of `std::cout` on every iteration due to `std::endl`. Try using `'\n'` instead. – Algirdas Preidžius Oct 25 '17 at 12:42
  • 1
    @AlgirdasPreid: I would assume that the Python print also performs a flush. –  Oct 25 '17 at 12:45
  • @YvesDaoust Why "assume", if you can check the [documentation](https://docs.python.org/2/library/functions.html#print)? "_Output buffering is determined by file. Use `file.flush()` to ensure, for instance, immediate appearance on a screen._" – Algirdas Preidžius Oct 25 '17 at 12:51
  • @AlgirdasPreid: I don't believe this statement. On an Idle console, prints are immediate, no need to flush. –  Oct 25 '17 at 12:53
  • @YvesDaoust I never used Python, so I don't have first-hand knowledge. All I know, is what's written in documentation, which states the thing that I quoted, which implies, that `print` itself does not perform a flush. If I am wrong, and am reading from the wrong documentation, you are free to link me to the documentation, which states that `print` performs flush as well. – Algirdas Preidžius Oct 25 '17 at 12:57
  • @AlgirdasPreid: should I link you to a Python console for a demo ? –  Oct 25 '17 at 13:00
  • @YvesDaoust If such demo would prove that it is flushed at the call site of `print`, and not because of synchronization between `stdin`, and `stdout`, due to, say, argument input, then sure. – Algirdas Preidžius Oct 25 '17 at 13:07
  • @AlgirdasPreid: of course, no input required. But the flushes might be periodically forced by an asynchronous process. –  Oct 25 '17 at 13:42
0

C++'s advantage in comparison with Python doesn't lie in operations constrained by the OS such as printing to the console, but rather:

  • The fact is it hard typed, thus minimizing run-time overhead due to dynamic typing and type safety
  • The fact C++ is compiled (and highly optimized) and Python is (mostly) interpreted
  • In it's memory management model (Python uses managed objects that require garbage collection)
  • C++ can give you more control when implementing performance critical code (as far as using assembly and taking advantage of specific hardware)
Daniel Trugman
  • 8,186
  • 20
  • 41
  • C++ is compiled, Python Is interpreted. That's the key point. –  Oct 25 '17 at 12:42
  • 1
    "or performing arithmetic operations" except that performing arithmetic operations in C++ is usually one or two orders of magnitude faster than in CPython. – Matteo Italia Oct 25 '17 at 12:44
  • 1
    @YvesDaoust, so you think that compiled python is as fast as c++? – Daniel Trugman Oct 25 '17 at 12:47
  • @DanielTrugman: there is no official Python compiler, and I doubt the available ones can beat the available C++ optimizers. And you need to compare comparable things, as the data structures in Python are much more flexible, polymorphic and run-time checked. For raw computation, yes, Python could be as fast. –  Oct 25 '17 at 12:51
  • There are interpreted implementations of C++ and compiled implementations of Python. The **implementations** that are relatively common (e.g. part of a Unix distribution) are the way round you say. – Caleth Oct 25 '17 at 12:52
  • @DanielTrugman: the expression Memory Management is misleading. Python relies on C's memory management. –  Oct 25 '17 at 12:57
  • @YvesDaoust, I added an explanation about the biggest disadvantage of Python's memory model – Daniel Trugman Oct 25 '17 at 12:59
  • @DanielTrugman: even Java uses managed objects that require garbage collection, but is way faster. The big performance problem in Python is the *extreme* dynamism mandated by its semantics, which kills almost any possibility of optimization based on static analysis - an opcode to sum two values needs to figure out the type of objects at each call, possibly with a nontrivial number of hashtable lookups; each time you call a function, the name lookup is done again because the environment may have been changed completely. Almost nothing can be done at compile time, because most of the... – Matteo Italia Oct 25 '17 at 16:54
  • ... semantics depends from the runtime environment. Compare this with C++: once you know that a variable is an `int`, an appropriate machine code to e.g. increment it can be generated. All function calls are resolved at compile time, including overloaded operators (which by the way allows inlining). The only form of built in dynamism is through virtual functions, which are opt-in and are easy to implement efficiently. Also, given that there's no `eval`, the compiler can do extra assumptions about the environment (e.g. no class derives from A -> all its methods can be inlined even if virtual). – Matteo Italia Oct 25 '17 at 17:00
  • So, the point is that memory management is just a secondary problem for Python; the big issue is that its semantics makes it essentially impossible to write a "classical" optimizing compiler with performance comparable to equivalent C++. In facts, what is done to have Python run fast is to use a JIT (PyPy) that tracks the interpreter execution to figure out what are the actual types/operations currently used in some block of code, and generate efficient code on the fly *just for these specific conditions*, reverting to interpreting once these conditions change. – Matteo Italia Oct 25 '17 at 17:10
  • @MatteoItalia, thank you very much for your input. You point out valuable information, and after reading your comments, to which I'm well aware, I understand that my first attempt at writing a concise answer to this question failed miserably. I hope that my latest answer contains the succinct list of bullets that make up the core foundation of the performance difference between the two languages. – Daniel Trugman Oct 25 '17 at 22:01