일을 하다 우연히 __attribute__((__cold__)) 옵션에 관하여 궁금해서 질문 드립니다.
커널소스에서도 이것을 사용하는지 찾아보았는데 include/linux/compiler-gcc4.h에 매크로로 __cold로 정의가 되있더군요. (gcc 버젼 4.3 이상일 경우만 해당.) 그리고 이것을 사용하는 것을 찾아 보았는데, 드라이버의 초기화 코드를 선언 할 때 자주 사용 하던 __init에서 사용되는 것을 볼 수 있었습니다.
#define __init __section(.init.text) __cold
이런식으로요.. ( 리눅스 커널 소스를 찾아 보았는데 linux-2.6.23 부터 추가가 되었습니다.)
이 헤더파일 주석에 있는 설명대로 최적화 관련 옵션으로 ulikely()같은 경우 처럼 생각하면 되는 건가요? 단지 브랜치 조건에 사용 하느냐 함수 자체에 사용하느냐가 틀린건가요?
이것을 사용하면 최적화 관련해서 어떤 이점이 생기는 것인지가 궁금하네요..??
커널소스에서도 이것을 사용하는지 찾아보았는데 include/linux/compiler-gcc4.h에 매크로로 __cold로 정의가 되있더군요. (gcc 버젼 4.3 이상일 경우만 해당.) 그리고 이것을 사용하는 것을 찾아 보았는데, 드라이버의 초기화 코드를 선언 할 때 자주 사용 하던 __init에서 사용되는 것을 볼 수 있었습니다.
#define __init __section(.init.text) __cold
이런식으로요.. ( 리눅스 커널 소스를 찾아 보았는데 linux-2.6.23 부터 추가가 되었습니다.)
이 헤더파일 주석에 있는 설명대로 최적화 관련 옵션으로 ulikely()같은 경우 처럼 생각하면 되는 건가요? 단지 브랜치 조건에 사용 하느냐 함수 자체에 사용하느냐가 틀린건가요?
이것을 사용하면 최적화 관련해서 어떤 이점이 생기는 것인지가 궁금하네요..??
댓글 12
-
원민수
2008.11.26 15:39
음.. 일단 __init은 성능 최적화 관련은 아닙니다. 메모리 최적화(?) 라고 할 수 있을 지 모르겠지만, __init의 경우에는 초기화가 끝나고 나면 메모리를 free 시키기 위해서 사용합니다. likely, unlikely의 경우가 성능 최적화인데, 말씀 하신 것처럼 brach로 인해서 pipe lining이 깨지는 것을 가급적 최소화 시키기 위해서 brach predition 시켜주는 것이지요. 실제로 likely, unlikely 매크로를 확인하면, gcc의 __builtin_expect()를 사용하고 있지요. 여하튼, 이점은 메모리에 대한 것이라고 해야 할까요? ㅎㅎ 그리고 likely, unlikely 용도와는 좀 다른 것이지요. -
원민수
2008.11.26 15:41
허걱.. 제가 올릴때 이백님도 같이 올리셨나 보군요.. 제가 올리고 나서 위에 답글이 있는걸 보고 놀랬습니다. ㅎㅎ 일단 이백님의 말씀 상태로라면, linux에서 cache 관련되서 hot, cold 영역이 있던걸로 기억하는데(역시 시간이 지나니 까먹게 되네요.. ㅠㅠ), 그러한 부분을 compiler 차원에서 지원해주는게 아닐까요? -
맥주
2008.11.26 15:46
아.. 추가 하려고 지우고 다시 쓰는데요 --;
http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Function-Attributes.html#Function-Attributes
을 읽어 보니, function이 잘 수행되지 않을때 사용하는 것 같네요.
이러한 function 은 수행 속도보다는 코드 사이즈로 최적화 되고,
text section의 특별한 subsection에 위치 하게 되어서 program 의 non-cold 부분에 대한 code locality 를 높인다고 하네요. 지역성이 높은 코드는 캐쉬 히트율이 높아지겠네요. 조은건가 봅니다. ^^ 4.3 이상 부터 된다네요.
그리고, branch prediction mechanism (분기예측) 에 의해서 파이프라인을 형성 할때 도움이 되겠네요. -
원민수
2008.11.26 16:00
ㅎㅎ 그렇군요.. 제가 잘못 생각한거네요. GCC compiler 팀에서 좀더 좋은 정보를 주실 수도 있을거 같네요. ㅎㅎ -
이상철
2008.11.26 16:23
질문올린지 얼마 안된거 같은데 벌써 답변을 달아주시니 감사합니다~^^ 어떤것인지 개념이 잡혔네요~ -
이상철
2008.11.26 16:48
문득 하나가 더 생각이 들었는데요~ 기존 __init 선언된것에 __cold를 사용하면 이점이 있나요? 커널 소스를 다시 찾아봤는데 이것이 사용된것이 printk, dump_stack, panic 같은 함수에서 사용이 됐더군요. 이것들은 어차피 디버깅용으로 더 많이 사용이 되니깐 __cold가 사용되서 이점이 있을 같다는 생각이 들지만, __init에서 사용한거는 제 생각으로는 조금 이상한거 같아서요.
__init으로 선언된 것들은 이미 섹션을 .init.text로 맞추어서 지역성을 높였다고 생각이 드는데, 지금 이해 한대로 생각해보면 __cold 를 사용해서 사이즈의 대한 최적화를 수행, 지역성을 더 높일 목적으로 사용 했다고 보면 되나요? 또 __init으로 선언된 것들은 적어도 초기화 코드에서 한번씩은 호출이 될 수 있기 때문에 분기예측에 대한 파이프라인 형성을 도와주는 역할을 못할거라는 생각도 드네요~ -
태훈
2008.11.26 16:59
제 생각에는 지역성 고려보다는 사이즈 최적화 목적으로 쓰인것 같네요.
__init에서 사용되는 함수들은 초기화 시점에만 쓰이고, 더이상 쓰이지 않기 때문에 커널 이미지 크기를 줄이기 위해 쓰이지 않나 생각합니다. -
맥주
2008.11.26 17:43
ㅎㅎ 태훈님 오랜만에 댓글 작열이십니다.
저도 태훈님 말씀에 동감..
지모모님 회사 검색기 돌려보니, 대충 이런 글이 보입니다.
This patch marks some common error functions like panic(), printk(), BUG() as cold. This will longer term make many unlikely()s unnecessary, although we can keep them for now for older compilers.
Also all __init and __exit functions are marked cold. With a non -Os build this will tell the compiler to generate slightly smaller code
for them. I think it currently only uses less alignments for labels,
but that might change in the future.
* section 를 정의하지 않은 dump_stack, panic, printk 는 .text.unlikely 섹션에 들어가 있네요.
-
백창우
2008.11.26 18:55
부팅 끝나고 해당 섹션을 free 시키기 위한 부분인것 같습니다. 한표 더 추가군요. -
이상철
2008.11.27 12:22
댓글 달아주신불들께 너무 감사드립니다~ 나중에 시간이 되면 gcc를 4.3으로 업데이트하고 한번 컴파일해봐야 겠네요. 사이즈가 얼마나 주는지~^^ 근데 백창우님이 마지막에 남기신 말을 어떤건지 잘이해가 안되네요..^^;; 좀 더 부가설명 해주시면 안되나요??^^;; -
백창우
2008.11.27 12:46
.init.??? 하는 섹션들은 초기 부팅 과정에서만 사용되는 코드가 들어가는 섹션입니다. 부팅이 끝나면 필요 없기 때문에 해당 섹션을 free 시켜버리죠.
그래서 보다 메모리를 효율적으로 사용할수 있습니다. 부팅시 한번만 사용하는 코드를 굳이 메모리에 보관할 필요가 없겠죠.
이것을 태훈님과 이백님이 확인해주셨고, 저는 그기에 한표 더 추가했다는 의미 입니다. -
이상철
2008.11.27 14:08
넵 감사합니다~^^
.