혼합 cout 및 printf 에 대한 빠르게 출력
-
20-09-2019 - |
문제
후에는 일부를 수행하는 테스트는 것으로 나타났 printf
보다 훨씬 더 빠르 cout
.내가 알고있는 그것의 구현은 의존하지만,내에서 리눅스 printf
입니다 8 배 더 빠릅니다.그래서 나의 생각은 두 가지를 혼합한 인쇄방법:을 사용하고 싶 cout
에 대한 간단한 인쇄물,그리고 나는 계획을 사용하기 printf
생산을 위한 거대한 출력(일반적으로는 루프에서).내가 안전하다고 생각하지로 나가는 것을 잊지 않을 세척하기 전에 전환하는 다른 방법:
cout << "Hello" << endl;
cout.flush();
for (int i=0; i<1000000; ++i) {
printf("World!\n");
}
fflush(stdout);
cout << "last line" << endl;
cout << flush;
그것은 좋아요?
업데이트: 에 대한 감사는 모든 소중한 피드백.요약의 답변:만약 당신이 피하고 싶은 까다로운 솔루션은 단순히 사용하지 않는 endl
가 cout
므로 플러시 버퍼를 사용한다.사 "\n"
대신 합니다.그것은 재미있을 수있는 경우를 생산 크 출력이 있습니다.
해결책
직접적인 대답은 그렇습니다. 괜찮다는 것입니다.
많은 사람들이 속도를 향상시키는 방법에 대한 다양한 아이디어를 던져 버렸지 만 가장 효과적인 일치가 상당히 불일치 한 것 같습니다. 나는 적어도 어떤 기술이 무엇을했는지에 대한 몇 가지 아이디어를 얻기 위해 빠른 시험 프로그램을 작성하기로 결정했습니다.
#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>
char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";
void show_time(void (*f)(), char const *caption) {
clock_t start = clock();
f();
clock_t ticks = clock()-start;
std::cerr << std::setw(30) << caption
<< ": "
<< (double)ticks/CLOCKS_PER_SEC << "\n";
}
void use_printf() {
for (int i=0; i<count; i++)
printf(fmt, string);
}
void use_puts() {
for (int i=0; i<count; i++)
puts(string);
}
void use_cout() {
for (int i=0; i<count; i++)
std::cout << string << "\n";
}
void use_cout_unsync() {
std::cout.sync_with_stdio(false);
for (int i=0; i<count; i++)
std::cout << string << "\n";
std::cout.sync_with_stdio(true);
}
void use_stringstream() {
std::stringstream temp;
for (int i=0; i<count; i++)
temp << string << "\n";
std::cout << temp.str();
}
void use_endl() {
for (int i=0; i<count; i++)
std::cout << string << std::endl;
}
void use_fill_n() {
std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}
void use_write() {
for (int i = 0; i < count; i++)
std::cout.write(s.data(), s.size());
}
int main() {
show_time(use_printf, "Time using printf");
show_time(use_puts, "Time using puts");
show_time(use_cout, "Time using cout (synced)");
show_time(use_cout_unsync, "Time using cout (un-synced)");
show_time(use_stringstream, "Time using stringstream");
show_time(use_endl, "Time using endl");
show_time(use_fill_n, "Time using fill_n");
show_time(use_write, "Time using write");
return 0;
}
VC ++ 2013 (X86 및 X64 버전 모두)으로 컴파일 한 후 Windows에서 이것을 실행했습니다. 한 번의 실행 (디스크 파일로 리디렉션 된 출력 포함)에서 출력이 다음과 같습니다.
Time using printf: 0.953
Time using puts: 0.567
Time using cout (synced): 0.736
Time using cout (un-synced): 0.714
Time using stringstream: 0.725
Time using endl: 20.097
Time using fill_n: 0.749
Time using write: 0.499
예상대로 결과는 다양하지만 흥미로운 점이 몇 가지 있습니다.
- Printf/Puts는 NUL 장치에 쓸 때 Cout보다 훨씬 빠릅니다.
- 하지만 Cout은 실제 파일에 쓸 때 꽤 멋지게 계속됩니다.
- 상당히 제안 된 최적화는 거의 달성하지 못했습니다
- 내 테스트에서 Fill_n은 다른 것만 큼 빠릅니다.
- 지금까지 가장 큰 최적화는 ENDL을 피하는 것입니다
- cout.write는 가장 빠른 시간을 주었다 (아마도 큰 마진은 아니지만
최근에 코드를 편집하여 전화를 강제로 편집했습니다. printf
. Anders Kaseorg는 지적하기에 충분히 친절했습니다 g++
특정 시퀀스를 인식합니다 printf("%s\n", foo);
동일합니다 puts(foo);
, 그에 따라 코드를 생성하고 (즉, 호출 할 코드를 생성합니다. puts
대신에 printf
). 형식 문자열을 글로벌 배열로 이동하고 형식 문자열이 동일한 출력을 생성하지만 printf
대신에 puts
. 물론, 그들은 언젠가 이것을 최적화 할 수 있지만 적어도 지금은 (G ++ 5.1) g++ -O3 -S
실제로 호출 중인지 확인합니다 printf
(이전 코드가 호출로 컴파일 된 경우 puts
).
다른 팁
배상 std::endl
스트림에 추가 a newline
스트림을 플러시합니다. 후속 호출 cout.flush()
불필요합니다. 타이밍이 완료된 경우 cout
vs. printf
그런 다음 사과를 사과와 비교하지 않았습니다.
기본적으로 C 및 C ++ 표준 출력 스트림은 동기화되므로 하나에 쓰기가 다른 플러시를 유발하므로 명백한 플러시가 필요하지 않습니다.
또한 C ++ 스트림은 C 스트림과 동기화됩니다.
따라서 동기화를 유지하는 데 추가 작업이 수행됩니다.
주목해야 할 또 다른 것은 스트림을 같은 양으로 플러시하는 것입니다. 한 시스템에서 스트림을 지속적으로 플러시하면 테스트 속도에 확실히 영향을 미치는 다른 시스템이 아닌 다른 시스템이 아닙니다.
하나가 다른 것보다 빠르다고 가정하기 전에 :
- CI/O의 UN-SYNC C ++ I/O (sync_with_stdio () 참조).
- 플러시의 양이 비슷한 지 확인하십시오.
성능을 더욱 향상시킬 수 있습니다 printf
버퍼 크기를 증가시켜 stdout
:
setvbuf (stdout, NULL, _IOFBF, 32768); // any value larger than 512 and also a
// a multiple of the system i/o buffer size is an improvement
I/O를 수행하기 위해 운영 체제에 대한 호출 수는 거의 항상 가장 비싼 구성 요소 및 성능 리미터입니다.
당연하지 만약 cout
출력은 혼합되어 있습니다 stdout
, 버퍼 플러시는 버퍼 크기가 증가한 목적을 물리칩니다.
당신이 사용할 수있는 sync_with_stdio
C ++ IO를 더 빨리 만들기 위해.
cout.sync_with_stdio(false);
출력 성능을 향상시켜야합니다 cout
.
에 대해 걱정하지 마십시오 성능을 사 printf
고 cout
.을 얻을하려는 경우의 성능,분리되는 포맷 출력에서 포맷 출력.
puts("Hello World\n")
보다 훨씬 더 빠르 printf("%s", "Hellow World\n")
. (주로 인해 서식 오버헤드). 면 당신은 고립 된 이 포맷에서 일반 텍스트를 수행할 수 있습니 tricks like:
const char hello[] = "Hello World\n";
cout.write(hello, sizeof(hello) - sizeof('\0'));
속도 포맷 출력을,트릭은 수행하는 모든 형식 문자열,다음 사용 블록을 출력 문자열로(또는 버퍼):
const unsigned int MAX_BUFFER_SIZE = 256;
char buffer[MAX_BUFFER_SIZE];
sprintf(buffer, "%d times is a charm.\n", 5);
unsigned int text_length = strlen(buffer) - sizeof('\0');
fwrite(buffer, 1, text_length, stdout);
를 더욱 개선하는 프로그램의 성능,수량을 줄일 수 출력합니다.더 적은 물건을 출력,더 빨리 프로그램이 될 것입니다.부작용이 있는 실행 파일 크기의 축소됩니다 너무입니다.
글쎄, 나는 Cout을 실제로 정직하게 사용해야 할 이유를 생각할 수 없습니다. 모든 파일에있을 정도로 간단한 일을하기 위해 거대한 부피가 큰 템플릿을 갖는 것은 완전히 미쳤다. 또한 가능한 한 느리게 입력하도록 설계되었으며 백만 번째 타이핑 <<<< 이후에 <<<< 다음 사이에 값을 입력하고 LIK> variableName >>>를 얻는 것과 같은 값을 입력 한 후에는 다시는 그렇게하고 싶지 않습니다. .
당신이 STD 네임 스페이스를 포함 시키면 말할 것도없이 세계는 결국 사라질 것이며, 입력 부담이 더욱 말도 안됩니다.
그러나 나는 printf를 많이 좋아하지 않습니다. 나를 위해, 해결책은 내 자신의 콘크리트 클래스를 만들고 그 안에 필요한 물건을 부르는 것입니다. 그런 다음 원하는 방식으로, 원하는 구현, 원하는 형식 등으로 정말 간단한 IO를 가질 수 있습니다 (일반적으로 플로트는 항상 한 가지 방법이되기를 원합니다. 모든 통화와 함께 서식하는 것은 농담입니다).
그래서 내가 입력 한 것은 "+debugiotype+"의 "+cplusplusmethod+"보다 더 세인됩니다. IMO는 적어도 "; dout ++;
그러나 당신은 당신이 원하는 것을 가질 수 있습니다. 많은 파일을 사용하면 컴파일 시간을 얼마나 향상시키는 지 놀랍습니다.
또한 C와 C ++를 믹싱하는 데 아무런 문제가 없으며, 단순히 수행해야하며, C를 사용하는 데 문제를 일으키는 것들을 사용하는 경우 처음에 C를 믹싱하는 데 어려움을 겪는 것이 안전합니다. C ++.
C ++와 C Iomethods를 혼합하는 것은 C ++ 책인 FYI에 대해 권장했습니다. 나는 C 함수가 C ++가 예상/보유 한 상태에 대한 트래려를 확신합니다.