By default reading with cin
is excruciatingly slow compared to its counterpart scanf
... when logic tells us it shouldn't:
- With
cin
a direct call is made to the function that knows what the type of the target variable is. - With
scanf
the function you have to read the format string (with the dozens of possibilities that exist) to know how you have to interpret the input and then process it.
However, with a simple example it is easy to see that reality is different:
#include <iostream>
#include <chrono>
#include <string>
void cinFunc()
{
int N;
for( int i=0; i<100000; i++)
std::cin >> N;
}
void scanfFunc()
{
int N;
for( int i=0; i<100000; i++)
scanf(" %d",&N);
}
template<typename Func>
void Test(std::string const& title, Func f)
{
auto start = std::chrono::steady_clock::now();
f();
auto end = std::chrono::steady_clock::now();
auto diff = end - start;
std::cout << "Test " << title << ":\t" << std::chrono::duration<double, std::milli>(diff).count() << " ms\n";
}
int main()
{
Test("cin",cinFunc);
Test("scanf",scanfFunc);
return EXIT_SUCCESS;
}
The program is executed with a file containing 200,000 1-digit integers separated by a space, and the results speak for themselves:
Test cin: 64.7967 ms
Test scanf: 49.855 ms
What is the reason that C++'s own reading is so slow? How can this situation be corrected?
By default
iostream
it is synchronized withstdio
to ensure that the standard input and output functions both fromC
andC++
share a single buffer, since without synchronization they would both have independent buffers, this would cause problems like:Without the synchronization you will never know if you will get
Holaadiosmundo
orHolamundoadios
oradiosholamundo
since bothprintf
andcout
they have different buffers in consequence the order is undefined. Unfortunately the sync issue introduces a significant performance penalty foriostream
, but it is possible to disable it if you don't intend to mixstdio
andiostream
.This would give a significant performance boost even better than
stdio
.I have looked at your code in cpp.sh and it
cin
is faster than with the use ofscanf
, seeing that I removed the optimizations and it is still fastercin
, "I don't know" what it should be considering your question and the times it shows , you can take a look at the online ide maybe I'm missing something.On the other hand you can use
std::ios::sync_with_stdio(false);
if you don't need synchronized with the standard c maybe that will help you.I have also looked at other online ides like coliru and the same thing, coliru uses GCC 7.1.0, in case it helps you, the coliru test does not have any optimization either and it is about
-std=c++11