스택큐힙리스트

C++에서 stdin에서 줄을 읽는 것이 Python보다 왜 훨씬 느린가요? 본문

카테고리 없음

C++에서 stdin에서 줄을 읽는 것이 Python보다 왜 훨씬 느린가요?

스택큐힙리스트 2023. 3. 25. 03:27
반응형

저는 파이썬과 C++을 사용하여 stdin에서 문자열 입력 라인을 비교하고 싶었고, C++ 코드가 동등한 파이썬 코드보다 10배 느리게 실행되는 것을 보고 충격을 받았습니다. 제 C++ 지식이 떨어지고 아직 파이썬 전문가가 아니기 때문에, 뭔가를 잘못하고 있는지 또는 잘못 이해하고 있는 것인지 알려주세요.

(요약 답변: cin.sync_with_stdio(false) 문구를 포함하거나 fgets 대신 사용하십시오.)

번역: cin.sync_with_stdio(false) 문구를 포함하거나 fgets 대신 사용하십시오.

결과 요약: 내 질문의 맨 아래로 스크롤해서 표를 확인하십시오.

C++ 코드:

#include

#include

using namespace std;

int main() {

string input_line;

long line_count = 0;

time_t start = time(NULL);

int sec;

int lps;

while (cin) {

getline(cin, input_line);

if (!cin.eof())

line_count++;

};

sec = (int) time(NULL) - start;

cerr << Read << line_count << lines in << sec << seconds.;

if (sec > 0) {

lps = line_count / sec;

cerr << LPS: << lps << endl;

} else

cerr << endl;

return 0;

}

// Compiled with:

// g++ -O3 -o readline_test_cpp foo.cpp

파이썬 상당한 일치:

#!/usr/bin/env python

import time

import sys

count = 0

start = time.time()

for line in sys.stdin:

count += 1

delta_sec = int(time.time() - start_time)

if delta_sec >= 0:

lines_per_sec = int(round(count/delta_sec))

print(Read {0} lines in {1} seconds. LPS: {2}.format(count, delta_sec,

lines_per_sec))

여기는 나의 결과입니다.

$ cat test_lines | ./readline_test_cpp

Read 5570000 lines in 9 seconds. LPS: 618889

$ cat test_lines | ./readline_test.py

Read 5570000 lines in 1 seconds. LPS: 5570000

저는 이를 맥 OS X v10.6.8 (스노우 레오파드)와 리눅스 2.6.32 (레드햇 리눅스 6.2)에서 모두 시도해 보았음을 언급해야 합니다. 전자는 맥북 프로이고, 후자는 매우 강력한 서버이지만 이는 크게 관련이 없습니다.

$ for i in {1..5}; do echo Test run $i at `date`; echo -n CPP:; cat test_lines | ./readline_test_cpp ; echo -n Python:; cat test_lines | ./readline_test.py ; done

Test run 1 at Mon Feb 20 21:29:28 EST 2012

CPP: Read 5570001 lines in 9 seconds. LPS: 618889

Python:Read 5570000 lines in 1 seconds. LPS: 5570000

Test run 2 at Mon Feb 20 21:29:39 EST 2012

CPP: Read 5570001 lines in 9 seconds. LPS: 618889

Python:Read 5570000 lines in 1 seconds. LPS: 5570000

Test run 3 at Mon Feb 20 21:29:50 EST 2012

CPP: Read 5570001 lines in 9 seconds. LPS: 618889

Python:Read 5570000 lines in 1 seconds. LPS: 5570000

Test run 4 at Mon Feb 20 21:30:01 EST 2012

CPP: Read 5570001 lines in 9 seconds. LPS: 618889

Python:Read 5570000 lines in 1 seconds. LPS: 5570000

Test run 5 at Mon Feb 20 21:30:11 EST 2012

CPP: Read 5570001 lines in 10 seconds. LPS: 557000

Python:Read 5570000 lines in 1 seconds. LPS: 5570000

작은 벤치마크 보충 설명 및 요약

완전성을 위해, 같은 상자와 원래 (동기화 된) C ++ 코드로 동일한 파일의 읽기 속도를 업데이트하려고 생각했습니다. 다시 말하지만, 이는 빠른 디스크에서 100M 라인 파일을 대상으로하는 것입니다. 여러 솔루션 / 접근 방법과 함께 비교는 다음과 같습니다 :

답변 1

요약: C++에서 다른 기본 설정 때문에 시스템 호출이 더 필요합니다.

기본적으로 cin은 stdio와 동기화되므로 입력 버퍼링을 피하게 됩니다. 메인의 맨 위에 이것을 추가하면 성능이 훨씬 향상됩니다.

std::ios_base::sync_with_stdio(false);

일반적으로, 입력 스트림이 버퍼링되면 한 번에 한 문자씩 읽는 대신 더 큰 덩어리로 읽을 수 있습니다. 이렇게 하면 일반적으로 비교적 비용이 큰 시스템 호출의 수를 줄일 수 있습니다. 그러나, FILE* 기반 stdio와 iostreams은 종종 별도의 구현과 따로운 버퍼를 가지고 있으므로 두 가지가 동시에 사용되면 문제가 발생할 수 있습니다. 예를 들어:

int myvalue1;

cin >> myvalue1;

int myvalue2;

scanf(%d,&myvalue2);

만약 cin가 실제로 필요한 것보다 더 많은 입력을 읽었다면, 두 번째 정수 값은 자체 독립적인 버퍼를 가진 scanf 함수에 대해 사용할 수 없습니다. 이는 예상치 못한 결과를 초래할 수 있습니다.

이를 피하기 위해 기본적으로 스트림은 stdio와 동기화됩니다. 이를 달성하는 일반적인 방법 중 하나는 stdio 함수를 사용하여 필요할 때마다 각 문자를 하나씩 읽는 것입니다. 그러나 이렇게하면 많은 오버헤드가 발생합니다. 입력 양이 적으면 큰 문제가 되지 않지만, 수백만 줄을 읽을 때는 성능 저하가 상당합니다.

다행히도, 도서관 디자이너들은 당신이 무엇을 하는지 알고 있다면 성능을 개선하기 위해 이 기능을 비활성화할 수 있도록 결정했습니다. 그래서 그들은 sync_with_stdio 방법을 제공했습니다. 이 링크에서 (강조 추가):

동기화가 꺼져 있다면, C++ 표준스트림은 독립적으로 I/O를 버퍼링할 수 있으며, 이는 일부 상황에서 크게 빠를 수 있습니다.

답변 2

Reading lines from stdin in C++ is much slower compared to Python due to several factors. One of the most significant factors is the difference in how each language handles input/output (I/O) operations. In C++, I/O operations are typically performed using the cin and cout objects, which can be slow due to the way they are implemented.

On the other hand, Python comes with built-in modules such as sys and io, which provide fast I/O operations. Python's input() and sys.stdin.readline() functions are highly optimized for reading input, making it much faster compared to C++.

Another factor that contributes to the slower performance of C++ when reading from stdin is the way strings are handled. In C++, string objects are typically constructed and destructed for each line read from stdin, which can be slow and inefficient. Python, on the other hand, uses a more optimized string representation, which is faster and more memory-efficient.

Additionally, C++ requires more boilerplate code to read input from stdin compared to Python. This can make reading from stdin more cumbersome and time-consuming, leading to slower performance.

In summary, the slower performance of C++ when reading lines from stdin compared to Python can be attributed to differences in how each language handles I/O operations, how strings are handled, and the amount of boilerplate code required for input reading. To optimize the performance of C++ when reading from stdin, developers can use more efficient I/O operations, optimize string handling, and minimize boilerplate code.

반응형
Comments