Extremely slow std::cout using MS Compiler
Asked Answered
B

2

5

I am printing progress of many iterations of a computation and the output is actually the slowest part of it, but only if I use Visual C++ compiler, MinGW works fine on the same system.

Consider following code:

#include <iostream>
#include <chrono>

using namespace std;
#define TO_SEC(Time) \
    chrono::duration_cast<chrono::duration<double> >(Time).count();
const int REPEATS = 100000;

int main() {
    auto start_time = chrono::steady_clock::now();

    for (int i = 1; i <= REPEATS; i++) 
        cout << '\r' << i << "/" << REPEATS;

    double run_time = TO_SEC(chrono::steady_clock::now() - start_time);
    cout << endl << run_time << "s" << endl;
}

Now the output I get when compiled with MinGW ("g++ source.cpp -std==c++11") is:

100000/100000 
0.428025s

Now the output I get when compiled with Visual C++ Compiler November 2013 ("cl.exe source.cpp") is:

100000/100000
133.991s

Which is quite preposterous. What comes to mind is that VC++ is conducting unnecessary flushes.

Would anybody know how to prevent this?

EDIT: The setup is:

gcc version 4.8.2 (GCC), target i686-pc-cygwin

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86

Windows 7 Professional N 64-bit with CPU i7-3630QM, 2.4GHz with 8.00GB RAM

Beforetime answered 25/3, 2014 at 11:48 Comment(17)
What compiler options you use in both cases? Are they the same?Lopes
Is it a Release or a Debug build in VS?Harry
It's default options, i.e.: "g++ source.cpp -std=c++11" and "cl.exe source.cpp"Beforetime
By default vc++ uses /Od where it disables any optimization for faster debugging.Event
Compiled "cl.exe /O2 source.cpp", runtime: 135.549sBeforetime
I get significantly different numbers: MinGW: 21.6672s. cl.exe: 53.1926s. Which version of MinGW's g++ are you using?Checkrein
I'm surprised nobody has asked this yet: What are the version numbers of g++ and cl that you are using? Also since this is a pointless benchmark: what hardware setup are you running on?Pyrophyllite
The only way that this program can take only 0.38 seconds is when output is buffered, like when it is redirected to a file. That speeds up the MSVC++ build as well, 0.64 sec on my machine. Writing sane code is the primary directive here, write output tuned to the human eye.Midriff
gcc version 4.8.2 (GCC) Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86 on Windows 7 Professional N 64-bit with CPU i7-3630QM, 2.4GHz with 8.00GB RAMBeforetime
@HansPassant would you have a suggestion on how to enforce this behaviour?Beforetime
I think HansPassant has hit the nail on the head, however this is comparing apples to oranges. You cannot compare a 64bit application to a 32bit one when trying to benchmark behavior. You need to isolate variables if you're going to benchmark.Pyrophyllite
@Pyrophyllite I have edited the post to use 32bit Gcc as well, however I did not feel that neither the precise version of the compiler nor the target platform are really important since the results are just completely different, suggesting that there is completely different semantic action when the above is invoked.Beforetime
@PunyOne actually your updated numbers show that it was, albeit minor. 32bit applications on a 64bit machine have an impedance that doesn't occur for 64bit applications. If this were a floating point test however the difference would most likely be dramatic. That said I think HansPassant is correct, something is fishy here.Pyrophyllite
that's odd, don't you get a compile error in VS? you are missing a return valueLyndseylyndsie
@Claptrap no, should it? From standard (draft N3690): "If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;"Beforetime
@PunyOne well VS gave me a syntax errorLyndseylyndsie
@Claptrap Interesting, however it works for me with the above listed compiler.Beforetime
P
13

std::cout in MSVC is slow (https://web.archive.org/web/20170329163751/https://connect.microsoft.com/VisualStudio/feedback/details/642876/std-wcout-is-ten-times-slower-than-wprintf-performance-bug-in-c-library).

It is an unfortunate consequence of how our C and C++ Standard Library implementations are designed. The problem is that when printing to the console (instead of, say, being redirected to a file), neither our C nor C++ I/O are buffered by default. This is sometimes concealed by the fact that C I/O functions like printf() and puts() temporarily enable buffering while doing their work.

Microsoft suggests this fix (to enable buffering on cout/stdout):

setvbuf(stdout, 0, _IOLBF, 4096)

You could also try with:

cout.sync_with_stdio(false);

but probably it won't make a difference.

Phagocyte answered 25/3, 2014 at 14:4 Comment(1)
Thank you, setvbuf(stdout, 0, _IOLBF, 4096) did the trick (runtime 3.20018s ).Beforetime
P
0

avoid using std::endl but use instead "\n". std::endl is supposed to flush according to the standard.

Philtre answered 28/3, 2014 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.