Domanda

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

È stato utile?

Soluzione

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.

Altri suggerimenti

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top