program story

C ++ 프로그램에서 scanf ()를 사용하는 것이 cin을 사용하는 것보다 빠릅니까?

inputbox 2020. 8. 3. 08:22
반응형

C ++ 프로그램에서 scanf ()를 사용하는 것이 cin을 사용하는 것보다 빠릅니까?


이것이 사실인지는 모르겠지만 사이트 제공 문제 중 하나에 대한 FAQ를 읽을 때 내 관심을 끌만 한 것을 발견했습니다.

입 / 출력 방법을 확인하십시오. C ++에서 cin 및 cout 사용이 너무 느립니다. 이것을 사용하면 적절한 양의 입력 또는 출력으로 문제를 해결할 수 없습니다. 대신 printf와 scanf를 사용하십시오.

누군가 이것을 명확히 할 수 있습니까? C ++ 프로그램에서 scanf ()실제로 사용 하는 것보다 cin >> something ? 그렇다면 C ++ 프로그램에서 사용하는 것이 좋습니다? 나는 C ++을 배우고 있지만 C에만 해당한다고 생각했습니다 ...


다음은 간단한 경우에 대한 간단한 테스트입니다. 표준 입력에서 숫자 목록을 읽고 XOR 모든 숫자를 읽는 프로그램입니다.

iostream 버전 :

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

scanf 버전 :

#include <stdio.h>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  while (1 == scanf("%d", &x))
    parity ^= x;
  printf("%d\n", parity);

  return 0;
}

결과

세 번째 프로그램을 사용하여 33,280,276의 난수를 포함하는 텍스트 파일을 생성했습니다. 실행 시간은 다음과 같습니다.

iostream version:  24.3 seconds
scanf version:      6.4 seconds

컴파일러의 최적화 설정을 변경해도 결과가 크게 바뀌지 않는 것 같습니다.

따라서 실제로 속도 차이가 있습니다.


편집 : 사용자 clyfish 는 속도 차이가 주로 CI / O 기능과 동기화를 유지하는 iostream I / O 기능으로 인한 것이라고 지적 합니다. 다음을 호출하여이 기능을 끌 수 있습니다 std::ios::sync_with_stdio(false);.

#include <iostream>

int main(int argc, char **argv) {

  int parity = 0;
  int x;

  std::ios::sync_with_stdio(false);

  while (std::cin >> x)
    parity ^= x;
  std::cout << parity << std::endl;

  return 0;
}

새로운 결과 :

iostream version:                       21.9 seconds
scanf version:                           6.8 seconds
iostream with sync_with_stdio(false):    5.5 seconds

C ++ iostream이 승리합니다! 이 내부 동기화 / 플러싱은 일반적으로 iostream i / o 속도를 늦추는 것으로 나타났습니다. stdio와 iostream을 혼합하지 않으면 끌 수 있으며 iostream이 가장 빠릅니다.

코드 : https://gist.github.com/3845568


http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma

Performance of cin/cout can be slow because they need to keep themselves in sync with the underlying C library. This is essential if both C IO and C++ IO is going to be used.

However, if you only going to use C++ IO, then simply use the below line before any IO operations.

std::ios::sync_with_stdio(false);

For more info on this, look at the corresponding libstdc++ docs.


Probably scanf is somewhat faster than using streams. Although streams provide a lot of type safety, and do not have to parse format strings at runtime, it usually has an advantage of not requiring excessive memory allocations (this depends on your compiler and runtime). That said, unless performance is your only end goal and you are in the critical path then you should really favour the safer (slower) methods.

There is a very delicious article written here by Herb Sutter "The String Formatters of Manor Farm" who goes into a lot of detail of the performance of string formatters like sscanf and lexical_cast and what kind of things were making them run slowly or quickly. This is kind of analogous, probably to the kind of things that would affect performance between C style IO and C++ style. The main difference with the formatters tended to be the type safety and the number of memory allocations.


I just spent an evening working on a problem on UVa Online (Factovisors, a very interesting problem, check it out):

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080

I was getting TLE (time limit exceeded) on my submissions. On these problem solving online judge sites, you have about a 2-3 second time limit to handle potentially thousands of test cases used to evaluate your solution. For computationally intensive problems like this one, every microsecond counts.

I was using the suggested algorithm (read about in the discussion forums for the site), but was still getting TLEs.

I changed just "cin >> n >> m" to "scanf( "%d %d", &n, &m )" and the few tiny "couts" to "printfs", and my TLE turned into "Accepted"!

So, yes, it can make a big difference, especially when time limits are short.


If you care about both performance and string formatting, do take a look at Matthew Wilson's FastFormat library.

edit -- link to accu publication on that library: http://accu.org/index.php/journals/1539


There are stdio implementations (libio) which implements FILE* as a C++ streambuf, and fprintf as a runtime format parser. IOstreams don't need runtime format parsing, that's all done at compile time. So, with the backends shared, it's reasonable to expect that iostreams is faster at runtime.


Yes iostream is slower than cstdio.
Yes you probably shouldn't use cstdio if you're developing in C++.
Having said that, there are even faster ways to get I/O than scanf if you don't care about formatting, type safety, blah, blah, blah...

For instance this is a custom routine to get a number from STDIN:

inline int get_number()
{
    int c;        
    int n = 0;

    while ((c = getchar_unlocked()) >= '0' && c <= '9')
    {
        // n = 10 * n + (c - '0');
        n = (n << 3) + ( n << 1 ) + c - '0';
    }
    return n;
}

The problem is that cin has a lot of overhead involved because it gives you an abstraction layer above scanf() calls. You shouldn't use scanf() over cin if you are writing C++ software because that is want cin is for. If you want performance, you probably wouldn't be writing I/O in C++ anyway.


The statements cin and cout in general use seem to be slower than scanf and printf in C++, but actually they are FASTER!

The thing is: In C++, whenever you use cin and cout, a synchronization process takes place by default that makes sure that if you use both scanf and cin in your program, then they both work in sync with each other. This sync process takes time. Hence cin and cout APPEAR to be slower.

However, if the synchronization process is set to not occur, cin is faster than scanf.

To skip the sync process, include the following code snippet in your program right in the beginning of main():

std::ios::sync_with_stdio(false);

Visit this site for more information.


#include <stdio.h>
#include <unistd.h>

#define likely(x)       __builtin_expect(!!(x), 1)
#define unlikely(x)     __builtin_expect(!!(x), 0)

static int scanuint(unsigned int* x)
{
  char c;
  *x = 0;

  do
  {
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while(c<'0' || c>'9');

  do
  {
      //*x = (*x<<3)+(*x<<1) + c - '0';
      *x = 10 * (*x) + c - '0';
      c = getchar_unlocked();
      if (unlikely(c==EOF)) return 1;
  } while ((c>='0' && c<='9'));

  return 0;
}

int main(int argc, char **argv) {

  int parity = 0;
  unsigned int x;

  while (1 != (scanuint(&x))) {
    parity ^= x;
  }
  parity ^=x;
  printf("%d\n", parity);

  return 0;
}

There's a bug at the end of the file, but this C code is dramatically faster than the faster C++ version.

paradox@scorpion 3845568-78602a3f95902f3f3ac63b6beecaa9719e28a6d6 ▶ make test        
time ./xor-c < rand.txt
360589110

real    0m11,336s
user    0m11,157s
sys 0m0,179s
time ./xor2-c < rand.txt
360589110

real    0m2,104s
user    0m1,959s
sys 0m0,144s
time ./xor-cpp < rand.txt
360589110

real    0m29,948s
user    0m29,809s
sys 0m0,140s
time ./xor-cpp-noflush < rand.txt
360589110

real    0m7,604s
user    0m7,480s
sys 0m0,123s

The original C++ took 30sec the C code took 2sec.


Even if scanf were faster than cin, it wouldn't matter. The vast majority of the time, you will be reading from the hard drive or the keyboard. Getting the raw data into your application takes orders of magnitude more time than it takes scanf or cin to process it.


Of course it's ridiculous to use cstdio over iostream. At least when you develop software (if you are already using c++ over c, then go all the way and use it's benefits instead of only suffering from it's disadvantages).

But in the online judge you are not developing software, you are creating a program that should be able to do things Microsoft software takes 60 seconds to achieve in 3 seconds!!!

So, in this case, the golden rule goes like (of course if you dont get into even more trouble by using java)

  • Use c++ and use all of it's power (and heaviness/slowness) to solve the problem
  • If you get time limited, then change the cins and couts for printfs and scanfs (if you get screwed up by using the class string, print like this: printf(%s,mystr.c_str());
  • If you still get time limited, then try to make some obvious optimizations (like avoiding too many embedded for/while/dowhiles or recursive functions). Also make sure to pass by reference objects that are too big...
  • If you still get time limited, then try changing std::vectors and sets for c-arrays.
  • If you still get time limited, then go on to the next problem...

참고URL : https://stackoverflow.com/questions/1042110/using-scanf-in-c-programs-is-faster-than-using-cin

반응형