다음과 같은 코드가 있습니다. test_1 과 test_65536 중에 어느 것이 더 빠를까요?
[test_1]
for (int j = 0; j < 65536; j++) // loop를 이용하여 "a++"을 65536번 실행 { a++; }
[test_65536]
a++; a++; a++; ... // 총 65536번
좀 더 면밀한 테스트를 위해서 프로젝트를 만들어 실행을 했습니다.
[테스트 환경]
Assembly 코드상으로 비교를 제대로 위해 최적화 옵션을 배제하였습니다.
CPU | Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz |
OS | Windows 7 |
Compiler | Microsoft Visual Studio 2012 Update 4 |
Compile Option | Optimization - Disabled (/Od) |
[테스트 코드]
다운로드 : loop_test.zip (Visual Studio 2012 project file, source code and assembly file 포함)
#include <windows.h> #include <iostream> using namespace std; #define LOOP16(A) (A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A);(A); #define LOOP256(A) LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A);LOOP16(A); #define LOOP4096(A) LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A);LOOP256(A); #define LOOP65536(A) LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A);LOOP4096(A); #define N 65536 #define COUNT 100000 void test_1(__int64 a) { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < N; j++) { a++; } } cout << "a=" << a << endl; } void test_16(__int64 a) { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < N / 16; j++) { LOOP16(a++); } } cout << "a=" << a << endl; } void test_256(__int64 a) { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < N / 256; j++) { LOOP256(a++); } } cout << "a=" << a << endl; } void test_4096(__int64 a) { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < N / 4096; j++) { LOOP4096(a++); } } cout << "a=" << a << endl; } void test_65536(__int64 a) { for (int i = 0; i < COUNT; i++) { for (int j = 0; j < N / 65536; j++) { LOOP65536(a++); } } cout << "a=" << a << endl; } int main() { DWORD begTick, endTick; // test_1 begTick = timeGetTime(); test_1(0); endTick = timeGetTime(); cout << "test_1 takes " << endTick - begTick << endl; // test_16 begTick = timeGetTime(); test_16(0); endTick = timeGetTime(); cout << "test_16 takes " << endTick - begTick << endl; // test_256 begTick = timeGetTime(); test_256(0); endTick = timeGetTime(); cout << "test_256 takes " << endTick - begTick << endl; // test_4096 begTick = timeGetTime(); test_4096(0); endTick = timeGetTime(); cout << "test_4096 takes " << endTick - begTick << endl; // test_65536 begTick = timeGetTime(); test_65536(0); endTick = timeGetTime(); cout << "test_65536 takes " << endTick - begTick << endl; return 0; }
[어셈블리 - test_1]
파란색이 루프(j) 처리 반복 루틴이고, 빨간색이 a++ 루틴입니다. "파란색-빨간색"이 65536번 반복되어 실행이 됩니다.
; 16 : { ; 17 : for (int j = 0; j < N; j++) mov DWORD PTR _j$1[ebp], 0 jmp SHORT $LN3@test_1 $LN2@test_1: mov ecx, DWORD PTR _j$1[ebp] add ecx, 1 mov DWORD PTR _j$1[ebp], ecx $LN3@test_1: cmp DWORD PTR _j$1[ebp], 65536 ; 00010000H jge SHORT $LN1@test_1 ; 18 : { ; 19 : a++; mov edx, DWORD PTR _a$[ebp] add edx, 1 mov eax, DWORD PTR _a$[ebp+4] adc eax, 0 mov DWORD PTR _a$[ebp], edx mov DWORD PTR _a$[ebp+4], eax ; 20 : } jmp SHORT $LN2@test_1 $LN1@test_1: ; 21 : } jmp SHORT $LN5@test_1 $LN4@test_1:
[어셈블리 - test_65536]
빨간색이 하나의 a++ 루틴입니다. 빨간색 코드만 아래위로 65536번 그대로 반복되어 일렬로 늘어져 있습니다.
; 66 : {; 67 : LOOP65536(a++); mov edx, DWORD PTR _a$[ebp] add edx, 1 mov eax, DWORD PTR _a$[ebp+4] adc eax, 0 mov DWORD PTR _a$[ebp], edx mov DWORD PTR _a$[ebp+4], eax mov edx, DWORD PTR _a$[ebp] add edx, 1 mov eax, DWORD PTR _a$[ebp+4] adc eax, 0 mov DWORD PTR _a$[ebp], edx mov DWORD PTR _a$[ebp+4], eax mov edx, DWORD PTR _a$[ebp] add edx, 1 mov eax, DWORD PTR _a$[ebp+4] adc eax, 0 mov DWORD PTR _a$[ebp], edx mov DWORD PTR _a$[ebp+4], eax ...
[실행 결과]
>loop_test
a=6553600000
test_1 takes 13935
a=6553600000
test_16 takes 12366
a=6553600000
test_256 takes 12605
a=6553600000
test_4096 takes 12961
a=6553600000
test_65536 takes 13584
[결론]
test_1 에서는 반복 횟수 확인을 하는 코드가 추가되어 test_65536보다 더 느려 질 것 같은데, 결과는 그리 차이가 나지 않는 것을 볼 수가 있습니다. 정확한 원인이 무엇일까요?
상기 코드에서 "a++"로 되어 있는 코드를 전부 "a=0"로 바꿔서 테스트를 해 봤습니다. 재미있는 결과가 나오네요.
test_1이 제일 느림. 그렇다고 해서 test_65536이 제일 빠른 것은 아님(test_256이 제일 빠르고 그 앞뒤로 느려 지는 결과가 나옴).
테스트 파일 : loop_test(a=0).zip