심심해서 직접 printf와 cout의 수행속도를 비교해봤다. 매우 정확하게 하려면 CPU 시뮬레이터에다 넣어서 싸이클 단위로 측정할 수도 있는데, 그건 너무 귀찮어서 다른 방법으로 테스트했다. 동일한 내용을 찍는 printf, cout 프로그램을 만들고 이 프로그램이 실행될 때 얼마나 많은 인스트럭션들이 실행되는지를 조사해봤다. 가정은 실행된 인스트럭션이 많으면 수행시간도 길다라는 것인데, x86 한 인스터럭션의 레이턴시는 제각각이어서 이런 가정이 완벽히 옳은 것은 아니다. 그래서 메모리 읽고 쓰기도 몇 번이나 일어났는지도 카운트 해봤다. 그래도 정수 나눗셈이나 부동소수점 계산이 있는 것이 아니므로 “실행된 명령어의 개수 = 수행 시간” 이라 봐도 큰 문제는 없다. 단순히 컴파일러가 printf, cout 을 호출하기 위해 생성한 코드의 크기만 비교하는 것은 수행 속도를 가늠하기에는 불충분하다. 이건 순전히 정적인 코드 크기이고, 속도를 가늠하려면 실제 런타임 때, printf, cout 내부에서도 얼마나 많은 코드가 수행이 되는지를 알아야만 한다. printf 같은 경우 내부에서 큰 루프를 돌면서 타입을 파싱하는 작업을 하기 때문에 호출 코드 양은 적어도 출력하는데는 많은 명령이 필요할 수 있기 때문이다. 테스트를 위해서 인텔에서 만든 PIN이라는 dynamic binary instrumentation 툴을 이용하였다. PIN 킹왕짱이라는… Test1: C++ cout
Test2: C/C++ printf
x86 플랫폼이고 컴파일러는 VC++ 2008 최적화 옵션을 두고 테스트 했다. 정확하게 말해 완전히 같은 내용을 출력해주는 코드는 아니다. 부동소숫점의 프리시전을 조절하는 것이 까다로워 대충 코딩했다. #include <stdio.h> 완벽하게 하려면 Test1, Test2 함수 내의 명령어 개수만 헤아려야 한다. 그런데 그게 좀 까다로와 전체 프로그램의 명령어 개수를 헤아렸다. 그리고 텅빈 main 함수를 가진 프로그램의 명령어 개수를 헤아려 대충 가늠했다. 두 액체의 무게를 비교하는데 용기 무게를 빼는 것과 같은 이치.
결과 1.1. Test1: C++ cout을 한 번 수행했을 때:
1.2. Test2: C/C++ printf를 한 번 수행했을 때:
그리고 Test1과 Test2를 각각 10,000번씩 루프 돌렸을 때도 테스트 해봤다. 이 경우는 for를 수행하는데 필요한 오버헤드도 고려된 경우. 2.1. Test1*10,000 결과:
2.2. Test2*10,000 결과:
Discussion 생각보다 그 차이는 심했다. 컴파일러 최적화를 했지만 함수 한번 호출하는데 필요한 명령어 개수는 C++ cout 프로그램이 printf보다 6배 정도 더 필요했다. 호출하는데 필요한 명령어 개수도 많은 연산자 오버로딩 코드로 인해 많음이 당연하고 (약 5배), 역시 많은 메모리 연산과 명령어가 필요했다 (약 5배). 그런데 이 함수들을 각각 1만번씩 돌렸을 때는 재밌는 결과가 나왔다. cout의 비용이 printf에 비해 약 2.6배 정도만 많았다. 한 번 호출할 때 들었던 6배의 비용에 비하면 많이 줄었다. 2.2.을 보면 printf 함수는 1만 번 반복 시 수행된 명령 개수가 한 번 호출하는데 들어간 비용의 1만배에 근접하게 나온다. 반면, cout은 고작 4천배 밖에 되지 않았다. 의아해서 cout 함수를 100번을 돌려서 비교해보니, 약 40배가 나왔다. 1만 번 반복시 4천배와 비교하면 정확하게 루프 반복 회수에 비례했다. 당연히 이렇게 나와야 하는 결과. 따라서 cout은 한 번 호출하는데 필요한 고정 비용이 상당히 크다는 것을 알 수 있다. printf/cout의 루프 횟수에 따른 명령어 개수 그래프를 그리면, 기울기는 2.6배 차이가 나고, y 절편은 약 6배 차이나는 그래프가 그려질 것이다. 참고로 루프를 관리하는데 필요한 명령의 개수는 미미하다. 최적화 없이 ++을 1만번 수행하는 루프는 약 10만개의 명령어를 실행한다. 결과 2에서 나온 명령어 개수들이 약 억 단위임을 보면 무시해도 별 문제 없음. 마지막으로 만번 반복 호출 시 수행시간을 측정해보면 printf가 약 3~4배 빠름을 알 수 있다. 실행된 명령어 개수 차이 보다는 실제 차이가 좀 더 남을 알 수 있다. 요약하면 한 번 호출하는데 필요한 cout의 비용은 printf에 비해 6배이나 호출이 반복될 때는 그 차이가 줄었다. 그렇다고 하더라도, 위 printf/cout과 같이 복잡한 내용을 출력할 경우에는 수행하는데 필요한 명령어 개수는 cout이 약 2.5배 이상 많이 들었다. 따라서 각자 잘 알아서 적절히 printf와 cout을 사용할 것.
최근 등록된 덧글
이 글을 보고 온라인 알고리..
by 김정은 at 02:45 리눅스 커널도 바닐라가 있죠.. by Corund at 07/03 궁금증이 이제야 풀리네요... by 유겸애비 at 07/03 아무래도 mpeg 코덱 특성 .. by object at 07/02 그런 건 아닙니다. 논문 중에.. by object at 07/02 최근에 LCD TV를 구입해서.. by kirrie at 07/02 Supreme Commander의 .. by daybreaker at 07/02 같은 입맛을 가지셨군요... by 덤덤 at 07/02 최근 등록된 트랙백
메뉴릿
|