문제
내가 발견한 경우 인쇄 긴 문자열(char*)를 사용하여 cout 것 인쇄 1 문자에서 시간에 화면 윈도우 7,비스타,리눅스를 사용하여(putty)을 이용하여 Visual C++2008Windows,G++리눅스에서.Printf 이 너무 빨리 내가 실제로 전환 cout 을 printf 대부분의 인쇄에서 프로젝트입니다.이것은 나를 혼란 때문에 이 질문 처럼 보이는 내 하나만을 이 문제를 해결합니다.
도 썼 cout 교체하는 것처럼 보인 비트 떨어져 바지 cout 에 comp
class rcout
{
public:
char buff[4096];
unsigned int size;
unsigned int length;
rcout()
{
size = 4096;
length = 0;
buff[0] = '\0';
}
~rcout()
{
printf("%s", buff);
}
rcout &operator<<(char *b)
{
strncpy(buff+length, b, size-length);
unsigned int i = strlen(b);
if(i+length >= size)
{
buff[size-1] = '\0';
printf("%s", buff);
b += (size-length) -1;
length = 0;
return (*this) << b;
}
else
length += i;
return (*this);
}
rcout &operator<<(int i)
{
char b[32];
_itoa_s(i, b, 10);
return (*this)<<b;
}
rcout &operator<<(float f)
{
char b[32];
sprintf_s(b, 32, "%f", f);
return (*this)<<b;
}
};
int main()
{
char buff[65536];
memset(buff, 0, 65536);
for(int i=0;i<3000;i++)
buff[i] = rand()%26 + 'A';
rcout() << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
Sleep(1000);
cout << "\n\nOk, now cout....\n\n";
cout << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
Sleep(1000);
cout << "\n\nOk, now me again....\n\n";
rcout() << buff << buff <<"\n---"<< 121 <<"---" << 1.21f <<"---\n";
Sleep(1000);
return 0;
}
어떤 아이디어를 왜 cout 인쇄 천천히니까?
해결책
노트:이 실험 결과는 MSVC에 유효합니다. 다른 라이브러리 구현에서는 결과가 다릅니다.
printf
~할 수 있었다 (많이) 더 빠릅니다 cout
. 하지만 printf
런타임에서 형식 문자열을 구문 분석하면 기능 호출이 훨씬 적고 실제로 동일한 작업을 수행하기 위해 적은 수의 명령어가 필요합니다. cout
. 다음은 내 실험의 요약입니다.
정적 명령의 수
일반적으로 cout
보다 많은 코드를 생성합니다 printf
. 우리는 다음을 가지고 있다고 말합니다 cout
일부 형식으로 인쇄 할 코드.
os << setw(width) << dec << "0x" << hex << addr << ": " << rtnname <<
": " << srccode << "(" << dec << lineno << ")" << endl;
최적화가있는 VC ++ 컴파일러에서 188 바이트 코드. 그러나 교체 할 때 printf
-기반 코드 만 42 바이트가 필요합니다.
동적으로 실행 된 명령의 수
정적 명령의 수는 정적 이진 코드의 차이를 알 수 있습니다. 더 중요한 것은 런타임에서 동적으로 실행되는 실제 명령 수입니다. 나는 또한 간단한 실험을했다 :
테스트 코드 :
int a = 1999;
char b = 'a';
unsigned int c = 4200000000;
long long int d = 987654321098765;
long long unsigned int e = 1234567890123456789;
float f = 3123.4578f;
double g = 3.141592654;
void Test1()
{
cout
<< "a:" << a << “\n”
<< "a:" << setfill('0') << setw(8) << a << “\n”
<< "b:" << b << “\n”
<< "c:" << c << “\n”
<< "d:" << d << “\n”
<< "e:" << e << “\n”
<< "f:" << setprecision(6) << f << “\n”
<< "g:" << setprecision(10) << g << endl;
}
void Test2()
{
fprintf(stdout,
"a:%d\n"
"a:%08d\n"
"b:%c\n"
"c:%u\n"
"d:%I64d\n"
"e:%I64u\n"
"f:%.2f\n"
"g:%.9lf\n",
a, a, b, c, d, e, f, g);
fflush(stdout);
}
int main()
{
DWORD A, B;
DWORD start = GetTickCount();
for (int i = 0; i < 10000; ++i)
Test1();
A = GetTickCount() - start;
start = GetTickCount();
for (int i = 0; i < 10000; ++i)
Test2();
B = GetTickCount() - start;
cerr << A << endl;
cerr << B << endl;
return 0;
}
Test1 (Cout)의 결과는 다음과 같습니다.
실행 된 지침 : 423,234,439
메모리 부하/저장 : 약. 320,000 및 980,000
- 경과 시간: 52 초
그럼, 무슨 일이야 printf
? 이것은 test2의 결과입니다.
실행 된 지침 : 164,800,800
메모리 부하/저장 : 약. 70,000 및 180,000
- 경과 시간: 13 초
이 기계와 컴파일러에서 printf
훨씬 더 빨랐습니다 cout
. 실행 된 지침의 수와로드/스토어 (캐시 미스의 #을 나타냄)에는 3 ~ 4 배의 차이가 있습니다.
나는 이것이 극단적 인 경우라는 것을 안다. 또한, 나는 그것을 주목해야합니다 cout
32/64 비트 데이터를 처리 할 때 훨씬 쉽고 32/64 플랫폼 독립성이 필요합니다. 항상 트레이드 오프가 있습니다. 사용 중입니다 cout
확인시 유형이 매우 까다 롭습니다.
괜찮아, cout
MSV에서는 단지 짜증납니다 :)
다른 팁
다른 컴퓨터에서 동일한 테스트를 시도하는 것이 좋습니다. 왜 이런 일이 일어나고 있는지에 대한 좋은 대답이 없습니다. 내가 말할 수있는 것은 Cout과 Printf의 속도 차이를 본 적이 없다는 것입니다. 또한 Linux에서 GCC 4.3.2를 사용하여 코드를 테스트했으며 차이가 없었습니다.
즉, Cout을 자신의 구현으로 쉽게 대체 할 수는 없습니다. 사실, Cout은 STD :: Ostream의 인스턴스입니다. 많이 ioStream 연산자에 과부하가 걸리는 다른 클래스와 상호 운용성에 필요한 기능이 내장되어 있습니다.
편집하다:
말하는 사람 printf
항상보다 빠릅니다 std::cout
간단합니다 잘못된. 방금 64 비트 AMD Athlon X2의 GCC 4.3.2 및 -o2 플래그와 함께 Minjang이 게시 한 테스트 코드를 실행했으며 Cout은 실제로였습니다. 더 빠르게.
다음 결과를 얻었습니다.
printf: 00:00:12.024
cout: 00:00:04.144
Cout은 항상 printf보다 빠릅니까? 아마 그렇지 않을 것입니다. 특히 구현 구현은 아닙니다. 그러나 최신 구현에서 ioStream은 런타임에 형식 문자열을 구문 분석하는 대신 컴파일 시간에 정수/부동/객체를 문자열로 변환하기 위해 어떤 기능을 호출 해야하는지 알고 있기 때문에 ioStream은 stdio보다 빠를 수 있습니다.
그러나 더 중요한 것은 printf 대 cout의 속도 구현에 따라 다릅니다, 따라서 OP가 묘사 한 문제는 쉽게 설명 할 수 없습니다.
전화 해보세요 ios::sync_with_stdio(false);
std :: cout/cin을 사용하기 전에, 물론, 당신은 당신의 프로그램에서 stdio와 iostream을 혼합하지 않으면, 이것은 나쁜 일입니다.
프로그래밍 경쟁에 대한 나의 경험을 바탕으로 Printf는 Cout보다 빠릅니다.
내 솔루션이 시간 제한 이전에 만들어지지 않았을 때를 여러 번 기억합니다. cin
/cout
, 동안 printf
/scanf
일했다.
그 외에도, 그것은 정상적인 것 같습니다 (적어도 나를 위해) cout
보다 느립니다 printf
, 더 많은 작업을 수행하기 때문입니다.
기를 작성해 주시는 모든 데이터는 ostringstream
먼저,다음 사용 cout
에 ostringstream
ko str()
.나 64-bit Windows7 Test1
이미보다 상당히 빠른 속도 Test2
(주 달라질 수 있습니다.)를 사용하는 ostringstream
을 구축하는 단 하나 문자열을 먼저 다음 사용 cout
그 추가 감소 Test1
아 실행 시간에 의해 요소의 약 3~4.야 #include <sstream>
.
I.e., 대체
void Test1()
{
cout
<< "a:" << a << "\n"
<< "a:" << setfill('0') << setw(8) << a << "\n"
<< "b:" << b << "\n"
<< "c:" << c << "\n"
<< "d:" << d << "\n"
<< "e:" << e << "\n"
<< "f:" << setprecision(6) << f << "\n"
<< "g:" << setprecision(10) << g << endl;
}
과:
void Test1()
{
ostringstream oss;
oss
<< "a:" << a << "\n"
<< "a:" << setfill('0') << setw(8) << a << "\n"
<< "b:" << b << "\n"
<< "c:" << c << "\n"
<< "d:" << d << "\n"
<< "e:" << e << "\n"
<< "f:" << setprecision(6) << f << "\n"
<< "g:" << setprecision(10) << g << endl;
cout << oss.str();
}
I suspect ostringstream
이렇게 훨씬 더 빠른 결과적으로의하지 않을 작성하려고 하면 시간을 전화 operator<<
에 cout
.나타났습 경험을 통해하는 횟수가 줄 당신이 쓰기 화면(작성하여 더 번)증가능(을 다시,당신의 마일리지 달라질 수 있습니다.)
E.g.,
void Foo1()
{
for(int i = 0; i < 10000; ++i) {
cout << "Foo1\n";
}
}
void Foo2()
{
std::string s;
for(int i = 0; i < 10000; ++i) {
s += "Foo2\n";
}
cout << s;
}
void Foo3()
{
std::ostringstream oss;
for(int i = 0; i < 10000; ++i) {
oss << "Foo3\n";
}
cout << oss.str();
}
내 경우에, Foo1
했 1,092ms, Foo2
했 234ms 고 Foo3
했 218ms. ostingstream
s 는 당신의 친구입니다.분명히 Foo2 및 Foo3 요구(사소)더 많은 메모리.을 비교하는 이에 대하여는 C 스타일의 기능도 sprintf
으로 버퍼를 작성하는 버퍼를 사용하여 fprintf
고 더 효율 Test2
(그러나 나를 위해 이것만의 성능 향상 Test2
에 의해 약 10%정도; cout
고 printf
실제로 다른 짐승 후드에서).
컴파일러:MinGW64(TDM 및 그에 포함된 라이브러리들).
사용해보십시오 ios::sync_with_stdio(false);
. std :: cin/cout를 사용하기 전에 언급하십시오. Stdio 또는 ioStream을 혼합하지는 않지만 ioStream 표준 스트림을 해당 표준 C 스트림과 동기화합니다. 예를 들어 -STD :: CIN/WCIN의 iOStream은 C Stream의 stdin과 동기화됩니다.
다음은 c ++ 스트림을 c printf만큼 빠르게 만들어야하는 hax입니다. 나는 그것을 테스트하지 않았지만 그것이 작동한다고 생각합니다.
ios_base::sync_with_stdio(0);