if-else에서 무엇을 if에서 처리해야할까?
글쓴이: gurugio / 작성시간: 월, 2009/07/20 - 3:33오후
그냥 피상적으로 if의 조건은 항상 체크되므로
좀더 참일 확률이 높은 조건을 써준다고만 알고 있었습니다.
스핀락을 만들어서 실험을 한번 해봤습니다.
회사에서 만든거라 수치까지는 올리지 못합니다만
그냥 공유차원에서 간단하게 설명하겠습니다.
CASE 1.
while (1)
{
if 락 변수의 값이 참인가?
continue
else
try-lock
}
CASE 2.
while (1)
{
if 락 변수의 값이 거짓인가?
try-lock
else
continue;
}
위의 2가지 케이스로 여러갯수의 스레드를 만들어서 돌려봤는데
2번이 미세하게 더 빠른 동작을 보여줬습니다.
제 가설은 이렇습니다.
1. 아무리 critical-section의 경쟁이 치열하다고 해도, 스핀락이 잠겨있는 시간이
풀려있는 시간보다 길지는 못할것 같습니다. 또 그래야 좋은 디자인일것 같구요.
2. if 문의 조건식은 계속 실행되므로 버스를 잠그거나 메모리를 직접 읽는 처리는
안하는게 좋을것 같습니다.
3. 점프를 덜 하는게 프로세서 파이프라인 유지에 좋으므로 if 문에는
좀더 참일 확률이 높은 조건을 쓰는게 좋을것 같습니다.
제 가설에 어떤 오류가 있을지 실험에 문제는 없는지 참고 말씀 부탁드립니다. ;-)
댓글
가설 4번으로
하나를 더 넣는다면,
4. if 조건식이 참(true)일 가능성이 높은 것부터 코딩한다.
부연 설명하면, 처리 대상 데이터가 KLDP 사용자의 나이라고 봤을때,
From:
*알지비 (메신저: rgbi3307(at)nate.com)
*학창시절 마이크로마우스를 만들었고, 10년동안 IT관련 개발자로 일하고 있음.
*틈틈히 커널연구회(http://www.kernel.kr/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))
From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))
그게 기본적인
그게 기본적인 전제인 것 같은데요.
----
http://www.planetmono.org
----
http://www.planetmono.org
단순한 if-else 문에
단순한 if-else 문에 대해 소스 레벨에서 성능을 따지는 것은 무의미합니다.
then 블록이 fall through할지, else 블록이 fall through 할지는
"그때그때 달라요" 인 문제니까요.
rgbi3307님이 추가하신 4번 항목은 컴파일러가 어찌할 수 없는 문제니까 항상 참일것으로 생각됩니다.
linux pthread 코드 중의
linux pthread 코드 중의 일부입니다.
trylock() 을 작성할 때,
잠겨있는 시간이 풀려있는 시간보다 적을 것이다라는 예측을 하는 것 자체가 별로 좋아보이지 않습니다.
if 의 조건문에 영향을 받을 정도의 진지한 응용을 배려하고 싶다면,
오히려 락에 동시에 접근하는 경우가 많은 응용을 배려하는 것이 바람직하겠죠.
OTL
이런 경우는 Branch
이런 경우는 Branch prediction 때문에 어떻게 코드를 짜도 크게 차이가 나지 않을겁니다.
(아시겠지만, prediction이 맞는 경우 - 대부분 맞고... - 인스트럭션 파이프라인도 거의 유지가 되기 때문에 파이프라인 플러쉬에 의한 오버헤드 차이도 거의 없을겁니다)
이런 마이크로 레벨에서의 최적화를 위한 노력은 (공부하기 위한 목적 이외의) 많은 경우에 별로 도움이 안될 것 같습니다. 마이크로 레벨의 최적화는 scope이 작아서 상대적으로 생각하기가 쉽기 때문에 많이들 하려는 유혹에 빠지는데, 그렇게 scope이 작은 경우는 대부분 compiler, runtime, architecture등에서 최적화를 해 주기 때문에 들이는 노력에 비해서 효과가 크지 않습니다. (embedded는 잘 모르겠는데, embedded platform에서 손으로 (어셈블리 레벨에서...) 최적화를 해서 크게 도움이 되는 경우가 많은 편인가요? - 컴파일러가 엄청 안좋다거나 해서...)
핵심적이지 않은
핵심적이지 않은 비교를 먼저 다 처리하고, else 를 쓸 때는 가능한한 조건 자체를 참이 되도록 하는 방법을 '보호절'이라고 하나봅니다.
성능은 둘째 치고 가독성면에서 적극 수용하고 있습니다.
emerge money
http://wiki.kldp.org/wiki.php/GentooInstallSimple - 명령어도 몇 개 안돼요~
http://xenosi.de/
https://xenosi.de/
else 가 더 빠르게 생성됩니다.
if
else if
else
위와 같은 코드라면 마지막 else 가 가장 빠르게 동작합니다. 따라서 성능을 생각하면 마지막에 가장 많이 오는 조건을 달아야 하죠
switch 도 동일하게 동작합니다.
switch
case
case
default
위 코드에서 default 가 가장 빠릅니다.
if 문의 경우 조건이 switch 로 변환될수 있을정도로 조건이 간단해야 합니다.
switch 의 최적화과정에서 점프 테이블을 만들수가 있는데 default 는 점프 테이블도 안타게 됩니다.
따라서 일부로 함수테이블을 만드는것보다 default 는 빠릅니다.
결과적으로 보면 case < 함수 테이블 < default 순으로 속도가 다르다고 합니다.
좀 오래된 책에서 본거라 현재는 다를수도 있겠죠
해당 블럭만 보면
해당 블럭만 보면 그렇겠지만, 사실 비교를 한 뒤에 else절이 수행되는 것이므로 else가 더 느립니다.
------------------------------
How many legs does a dog have?
------------------------------
How many legs does a dog have?
그래서 이런 경우를
그래서 이런 경우를 위해 gcc에는 branch prediction을 컴파일러 레벨에서 도움을 줄수 있도록 __builtin_expect()을 제공하고 있습니다. Linux kernel에서 likely()/unlikely()가 macro하고 있는 기능입니다. 자세한 것은 http://kerneltrap.org/node/4705 를 참조하세요.
gcc의 likely 등에서
gcc의 likely 등에서 처리하는 것을 봐도
최대한 브랜치를 없애는게 좋다고 알고 있었습니다.
그래서 if에 확률이 높은 경우를 두면 비교&브랜치를 줄일 수 있지 않을까
생각을 했습니다.
제가 요즘 대용량 서버 환경으로 옮겨와서 최적화를 좀더 신경쓰고 있는데요
코드 몇줄을 생각하는 것보다, 상황이나 확률에 대해 추론하는게 역시 더 어렵네요.
지금 경우도 락을 한방에 얻을게 더 확률이 클 것인가
스핀을 돌게되면 얼마나 오래 돌 것인가 루프만 돌 것이냐 슬립도 넣을 것이냐 등등
이런 결정 사항들도 부분적인 설계 사항에 들어가겠지요?
----
섬기며 사랑하면 더 행복해집니다.
몸에 좋은 칼슘이 듬뿍담긴 OS 프로젝트 - 칼슘OS http://caoskernel.org
댓글 달기