Slow reading cin

6

By default the reading with cin is desperately slow compared to its counterpart scanf ... when logic tells us that it should not be like this:

  • With cin a direct call is made to the function that knows what the type of the destination variable is.
  • With scanf the function must read the format string (with the dozens of possibilities that exist) to know how to interpret the entry and then process it.

However with a simple example it is easy to see that the 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 runs 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 the reading of C ++ itself is so slow? How can this situation be corrected?

    
asked by eferion 22.06.2017 в 10:36
source

2 answers

5

By default iostream is synchronized with stdio to ensure that the standard input and output functions of both C and C++ share a single buffer, since without synchronization both would have independent buffers, this would cause problems like:

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    cout << "Hola";
    printf("mundo");
    cout << "adios";
}

Without the synchronization you will never know if you will get Holaadiosmundo or Holamundoadios or adiosholamundo since both printf and cout have different buffers, consequently the order is undefined. Unfortunately the issue of synchronization introduces a significant performance penalty for iostream , but it is possible to deactivate it if you do not intend to mix stdio and iostream .

ios_base::sync_with_stdio(false);

This would result in a significant increase in performance even better than stdio .

    
answered by 22.06.2017 / 18:26
source
2

I've looked at your code in cpp.sh and the cin is faster than with the use of scanf , seeing that I removed the optimizations and it is still faster the cin , "I do not know" that you should be keeping in mind your question and the times it shows, you can take a look at the online idea maybe something is happening to me.

On the other hand you can use std::ios::sync_with_stdio(false); if you do not need to synchronized with the standard c Maybe that will help you.

I've also looked at other ide online like coliru and the same, coliru uses GCC 7.1.0, for if it's helpful, the coliru test also has no optimization and it's about -std=c++11

    
answered by 22.06.2017 в 14:43