[리눅스/커널] 커널에서 자주 사용되는 매크로 : likely( ) / unlikely( )

by Blogger 하얀쿠아
2012. 11. 23. 17:04 소프트웨어 Note/Linux

커널에서 자주 사용되는 매크로 : likely( ) / unlikely( )

커널 소스를 보다보면 likely 또는 unlikely 메크로를 자주 사용하는 것을 볼 수 있습니다.


likely / unlikely macro가 어떤 의미를 가지는 매크로인지 궁금했어요.

그래서 알아보았죠.


커널 3.2 코드를 기준으로 likely / unlikely macro는 커널 소스에 다음과 같이 정의되어 있더군요.


소스위치는 ./include/linux/compiler.h


109 /*

110  * Using __builtin_constant_p(x) to ignore cases where the return

111  * value is always the same.  This idea is taken from a similar patch

112  * written by Daniel Walker.

113  */

114 # ifndef likely

115 #  define likely(x)     (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))

116 # endif

117 # ifndef unlikely

118 #  define unlikely(x)   (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))

119 # endif


볼드체로 표시된 부분을 주목해 보시죠.


likely 매크로 내부의 __builtin_constant_p  메크로는 branch prediction 정보를 컴파일러에게 알려주는 기능을 합니다.


쉽게 말하면, if문을 작성할 때 프로그래머가 컴파일러에게 '이 코드는 true(or false) 일 것 같다' 라고 말을 해주는 것과 같은 역할을 한다고 볼 수 있습니다.

컴파일러는 이 정보를 바탕으로 최적화된 branch 코드를 생성해 낸다고 하네요.


조금 전문적으로 말해볼까요.

likely / unlikely 매크로는 '수동 분기예측'을 하는 것인데, likely일것 같은 코드를 분기문의 바로 다음에 위치하도록 해서 CPU의 파이프라이닝이 계속 유효한 상태가 되도록 만들어주어 성능 향상을 도모합니다. 

참고로 x86프로세서는 성능을 높이기 위해서 파이프라인으로 동작하게 되는데요.

코드의 실행 중 분기문(branch)을 만나게 되면, 미리 fetch해온 코드를 flush 한 후, 분기할 곳을 다시 fetch하기 때문에 파이프라인이 깨져서 성능이 떨어지게 됩니다.


따라서 가능하면 분기를 하지 않도록 코드를 작성하는 것이 성능을 높이는데 도움이 됩니다.

이를 위해서 조건문이 true일 가능성이 높은지 false 일 가능성이 높은지를 프로그래머가 미리 컴파일러에게 알려주기 위해서 likely 또는 unlikely 매크로를 사용하는 것이죠.


조금 더 예제가 필요하시면, 아래 homepage를 방문해 보세요.


Kernel Newbies FAQ : https://kernelnewbies.org/FAQ/LikelyUnlikely

이 댓글을 비밀 댓글로
    • sejun
    • 2013.02.21 04:28
    잘 보고 갑니다.

    그런데 __branch_check_(x, expect) 메크로를 직접 분석하신 건가요;;?

    암호문처럼 써있는데 이런건 어떻게 해야 쉽게 분석이 가능할까요 ..