본문 바로가기

Creation/Programming

[C/C++] int와 register int의 속도 차이

 

Register Int에 대해서 알아보기

 

 

  C언어든 C++이든 결국 컴파일러를 거치면 어셈블리로 전환이 될 것입니다. 이는 곧 기계어와 동치이고.. 이렇듯 C언어는 바로 하드웨어와 연관이 있는 언어이므로, 이 하드웨어와 관련있는 코딩 구문들도 상당수 존재합니다.

  오늘 쓰는 내용은 register int에 관한 내용인데, 어떤 내용인지 코드를 통해 우선 먼저 보도록 합시다.

 

int main() {
    int tmp1 = 0;
    int tmp2 = 0;
    clock_t clk1 = clock();
    for (int i = 0; i < 10000; i++) {
        for (int j = 0; j < 10000; j++) {
            tmp1 += i;
        }
    }
    cout << "1: " << clock() - clk1 << "ms" << endl;
    
    clock_t clk2 = clock();
    for (register int i = 0; i < 10000; i++) {
        for (register int j = 0; j < 10000; j++) {
            tmp2 += i;
        }
    }
    cout << "2: " << clock() - clk2 << "ms" << endl;
}


  어떨까요? 1번이 빠를까요, 2번이 빠를까요? 아님 같을까요?

물론 문제 출제 의도 상 2번이 빠를 것 같으시겠지만 그래도 컴파일러를 거치는데 당연히 1/2번이 같게 되지 않겠냐.. 하시겠지만

놀랍게도 최적화 옵션 없이 컴파일하여 속도를 측정해보면 아래와 같은 결과가 나옵니다.

 

 

  미세하게나마 2번이 조금 더 빠른 것을 알 수 있습니다. 괄목할 만한 성능 차이는 아닙니다만, 최적화 성능이 요구되는 알고리즘 시험 등에서는 유용하게 쓰일 수 있는 사실이 아닐까 싶습니다. (약간이라도 빠른게 높은 점수에 유리하니)

 

  이런 결과가 나오는 것을 추측해보건데 CPU에 있는 register에 해당하는 변수를 우선적으로 배치함으로써 이런 성능차이가 벌어지지 않았나 싶습니다. 즉, 무작정 큰 배열을 register int a[10000]과 같은 식으로 해보았자 전혀 의미가 없겠죠. CPU의 레지스터 숫자는 굉장히 한정적이니까요. 컴파일러에게 무조건 register를 붙여준다고 해서 레지스터를 사용하지는 못할 것입니다. 그렇다고 할지라도 우선적으로 배치해라라는 명령어 정도는 내릴 수 있을 것이고 이것의 역할을 하는 것이 register인 것입니다. 이 상황에 가장 적합한 것이 매 loop마다 계속해서 값이 바뀌고 참고해야하는 for문의 변수인 것이죠. (물론 눈치빠른 컴파일러는, 특히 최적화 옵션을 키면 아마 바로 이 부분의 최적화에 들어갈 것입니다만)

 

  역시 하드웨어까지 다룰 수 있는 갓-C언어 답습니다.