programing

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

prostudy 2022. 7. 6. 22:04
반응형

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

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

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


편집: 사용자 clifish는 속도 차이는 주로 iostream I/O 함수가 C 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

★★★의 cin/cout는 기본 C 라이브러리와 동기화 상태를 유지해야 하기 때문에 속도가 느려질 수 있습니다.C IO C++ IO 。

다만, C++ IO만을 사용하는 경우는, I/O 조작 전에 다음의 행을 사용해 주세요.

std::ios::sync_with_stdio(false);

이에 대한 자세한 내용은 대응하는 libstdc++ 문서를 참조하십시오.

「」cin ★★★★★★★★★★★★★★★★★」cout으로는 것 scanf ★★★★★★★★★★★★★★★★★」printfC++ 를 c 、 C++ ! c 、 C+ ! c! 。

에서는 C++를 사용할 마다 사용 cin ★★★★★★★★★★★★★★★★★」cout되어 「」를 양쪽 하고 있는 는, 「」를 해 주세요scanf ★★★★★★★★★★★★★★★★★」cin프로그램에서는 둘 다 동시에 동작합니다.이 동기화 프로세스에는 시간이 걸립니다. 때문에, 「 」는 할 수 없습니다.cin ★★★★★★★★★★★★★★★★★」cout속도가 느린 것 같습니다.

하지 않게 되어 있는 는, 「」, 「」, 「」, 「」입니다.cinscanf.

프로세스를 , 합니다.main():

std::ios::sync_with_stdio(false);

상세한 것에 대하여는, 이 사이트를 참조해 주세요.

UVa Online(팩토비저스, 매우 흥미로운 문제, 확인해 보세요)에 관한 문제에 대해 하룻밤을 보냈습니다.

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

나는 제출물에 대해 TLE(기한 초과)를 받고 있었다.이러한 온라인 판사의 문제 해결 사이트에서는 솔루션을 평가하는 데 사용될 수 있는 수천 건의 테스트 사례를 처리하는 데 약 2-3초의 제한 시간이 있습니다.이와 같은 계산 부하가 높은 문제에서는 마이크로초당 1초가 중요합니다.

권장 알고리즘(사이트 토론 포럼에서 확인)을 사용하고 있었지만, 아직 TLEs를 취득하고 있었습니다.

"cin >> n >> m"을 "scanf ( %d %d , & n , & m )"로, 작은 "couts"를 "printfs"로 변경했습니다만, TLE는 "Accepted"로 바뀌었습니다.

그래서, 네, 그것은 큰 차이를 만들 수 있습니다. 특히 시간 제한이 짧을 때는요.

물론 iostream에서 cstdio를 사용하는 것은 말도 안 됩니다.적어도 소프트웨어를 개발할 때는 (이미 c++를 사용하고 있는 경우는, 단점만을 가지고 있는 것이 아니라, 그 장점을 끝까지 사용해 주세요).

그러나 온라인 심사에서는 소프트웨어를 개발하고 있지 않습니다.Microsoft 소프트웨어가 3초만에 실현하는 데 60초가 걸리는 작업을 수행할 수 있는 프로그램을 만들고 있습니다.

따라서 이 경우 황금규칙은 다음과 같습니다(물론 자바 사용으로 더 이상 문제가 발생하지 않는다면).

  • c++를 사용하여 전력(및 중량/저속)을 모두 사용하여 문제를 해결합니다.
  • 시간이 한정되어 있는 경우는, printfs 와 scanfs 의 cins 와 couts 를 변경합니다(클래스 스트링을 사용해 문제가 생겼을 경우는, 다음과 같이 인쇄합니다).
  • 그래도 시간이 한정되어 있는 경우는, 몇개의 명확한 최적화를 실시합니다(예를 들면, 너무 많은 임베디드 기능/시간중/잠금 기능 또는 재귀 함수를 사용하지 않는 등).또, 너무 큰 참조 오브젝트는 반드시 지나쳐 주세요.
  • 그래도 시간이 제한될 경우 std::: 벡터 및 c-array 세트를 변경해 보십시오.
  • 그래도 시간이 한정되어 있으면 다음 문제로 넘어가세요.
#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;
}

파일 끝에 버그가 있지만, 이 C코드는 더 빠른 C++ 버전보다 훨씬 빠릅니다.

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

원래 C++는 30초, C코드는 2초가 걸렸습니다.

아마도 scanf가 스트림을 사용하는 것보다 다소 빠를 것입니다.스트림은 많은 유형의 안전성을 제공하며 런타임에 포맷 문자열을 해석할 필요가 없지만 일반적으로 과도한 메모리 할당이 필요하지 않다는 장점이 있습니다(이는 컴파일러와 런타임에 따라 다름).단, 퍼포먼스가 유일한 최종 목표가 아니고, 중요한 경로에 있는 경우를 제외하고, 보다 안전한(느린) 방법을 정말로 선호해야 합니다.

Herb Sutter "The String Formters of Manor Farm"에 의해 쓰여진 매우 맛있는 기사가 여기 있습니다. 그는 다음과 같은 현악기 포메터들의 연주에 대해 많은 세부사항을 가지고 있습니다.sscanf그리고.lexical_cast어떤 것들이 느리게 또는 빠르게 작동하게 만드는지요.이는 C스타일의 IO와 C++스타일의 퍼포먼스에 영향을 주는 것과 비슷합니다.포메터의 주된 차이는 타입의 안전성과 메모리 할당의 수였습니다.

퍼포먼스와 스트링 포맷을 모두 중시하는 경우는, Matthew Wilson의 FastFormat 라이브러리를 봐 주세요.

edit -- 해당 라이브러리의 게시물에 대한 링크: http://accu.org/index.php/journals/1539

문제는 말이다cin위의 추상화 레이어를 제공하기 때문에 많은 오버헤드가 수반됩니다.scanf()콜을 사용하면 안 됩니다.scanf()에 걸쳐서cinC++ 소프트웨어를 쓰고 있는 경우는, 그것이 필요하기 때문에cin를 위한 것입니다.퍼포먼스를 필요로 하는 경우는, 어쨌든 I/O를 C++로 쓸 필요는 없습니다.

네, iostream은 cstdio보다 느립니다.
네, C++로 개발하시는 경우에는 cstdio를 사용하지 않는 것이 좋습니다.
그렇다고 해도 포맷에 신경 쓰지 않고 safety, blah, blah, blah, blah, blah...를 입력하면 스캔프보다 I/O를 더 빨리 얻을 수 있는 방법이 있습니다.

예를 들어 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;
}

scanf 빨랐다cin하지 않아요을 사용하다대부분의 경우 하드 드라이브 또는 키보드에서 읽습니다.원시 데이터를 애플리케이션에 가져오는 데 걸리는 시간보다 훨씬 더 많은 시간이 소요됩니다.scanf ★★★★★★★★★★★★★★★★★」cin처리할 수 있습니다.

파일*을 C++ 스트림버프로, fprintf를 런타임 포맷 파서로 구현하는 stdio 실장(libio)이 있습니다.IOStreams는 런타임 포맷의 해석은 필요 없습니다.이것은 모두 컴파일시에 실행됩니다.따라서 백엔드를 공유하면 실행 시 iostream이 더 빠를 것으로 예상할 수 있습니다.

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

반응형