if문에 대한 성능 질문입니다.
글쓴이: kid1402 / 작성시간: 월, 2012/06/11 - 5:18오후
함수에서 파라미터들의 Validity 체크를 할 때, if 문 하나에 한꺼번에 다 체크하는 것이 성능이 좋을지, 아니면 그냥 하나하나 체크해주는게 좋을 지 궁금합니다.(하나에 다 넣어도 컴파일러가 최적화 해주려나요?)
예를 들어
BOOL CRegistry::SetValue(LPCTSTR valueName, DWORD value) { if( !valueName || !value || !mIsOpened) { return FALSE; } ....
BOOL CRegistry::SetValue(LPCTSTR valueName, DWORD value) { if( !valueName) { return FALSE; } if( !value) { return FALSE; } if( !mIsOpened ) { return FALSE; } ....
이 두 코드중 어떤것이 더 성능에 좋을까요?
혹은 성능에 끼치는 영향이 적을까요?
이와 관련해서 의견이 궁금합니다
Forums:
컴파일러 최적화를 사용하지 않는다고 가정하면, 첫번째
컴파일러 최적화를 사용하지 않는다고 가정하면, 첫번째 예가 나은 성능을 보여줄 것으로 생각됩니다. 왜냐면 두번째 예는 파라미터 체크가 끝날 때 까지 세 번의 점프 명령을 수행할 지도 모르기 때문입니다. 보통 점프 명령은 파이프라인에 들어있던 명령을 모두 버려야하기 때문에 페널티가 매우 큽니다.
생산적인 댓글을 달자
short-circuit evaluation
제 생각에는 질문자께서 보여주신 첫 번째 경우가 short-circuit evaluation 조건에 의해서 컴파일러 옵션과 상관없이
두 번째 경우와 같은 성능을 나타낼 거라 생각됩니다.
여기서 short-circuit이 먹힐려면
여기서 short-circuit이 먹힐려면 valueName이 NULL이여야 하는데 그건 아마 파라미터가 잘못들어왔을 때, 즉 비정상적인 호출을 받았을 때입니다.
이 함수가 얼마만큼의 빈도로 비정상적인 호출을 당할 지는 저도 잘 모르겠지만, 평소에는 정상적으로 호출될 것이며 어쩌다가 잘못된 파라미터가 들어올 때 FALSE로 빠질 것이라고 예측했습니다.
때문에 저는 첫번째 두번째 모두 FALSE로는 잘 빠지지 않고 그 아래의 원래 함수처리를 수행한다는 가정하에 말씀을 드렸습니다.
생산적인 댓글을 달자
앞의 두 조건이 모두 거짓이라도
앞의 두 조건 "!valueName" 과 "!value" 이 거짓이라도
(즉 valueName 와 value 값이 "true" 일지라도)
첫 번째 경우와 두 번째 경우의 성능 차이는 거의 없을걸로 보입니다. (아래 gurugio 님의 답글에서 설명하신 것처럼...)
sohn9086 께서 말씀하신 jump 명령의 실행 횟수가 질문자께서 올린 첫 번째 경우와 두 번째 경우 같을 것 같습니다.
최적화보다 더 중요한 가독성을 생각했을 때는 첫번째
최적화보다 더 중요한 가독성을 생각했을 때는 첫번째 예의 방식으로 프로그래밍하는게 좋을것 같습니다.
제가 알기로는 컴파일러가 특정 statement를 한꺼번에 처리하느냐 한 부분씩 처리하느냐에 따라 다르기도합니다.
if (a & b & c)라는 문장을 처리할 때,
d = a & b & c;
if (d) ...
이렇게 처리할때는 기계어로
mov d, a
and d, b
and d, c
이렇게 될 수 있지만, 만약에 한 구문씩 처리한다면,
cmp a, NULL
je LABELA
cmp b, NULL
je LABELC
...
이렇게 컴파일될것 같습니다.
제가 알기로는 C 컴파일러는 두번째 방식으로 한 구문씩 처리한다고 들었습니다.
전체 문장을 모두 번역하지않고 하나의 조건만이라도 거짓이되면 다음 조건은 판단하지않고
바로 문장 전체를 거짓으로 판단한다고 들었습니다.
따라서 말씀하신 두 예제가 기계어로 변환되는 것도 원칙대로라면 비슷해야할것 같습니다.
그런데 최적화 기술이 적용될 것이니까 좀 다를 수는 있겠지요.
만약 첫번째 예제가 좀더 빠르다해도 그 차이가 아주 미미해서 결과적으로 드러나는 차이는 없을것 같습니다.
요즘 컴파일러 성능도 매우 좋고 요즘 cpu의
요즘 컴파일러 성능도 매우 좋고 요즘 cpu의 분기예측 성능 또한 매우 좋습니다.
컴파일러 성능이 매우 안좋고 분기예측 기능이 없는 cpu를 쓴다면 고민을 해봐야할 사항이나 우리가 사용하는 컴퓨터에서는 굳이 고민하지 않아도 알아서 최적화 잘 해줍니다.
그런것 보다는 전체적인 디자인(설계)에 더 집중하시는 것을 추천합니다.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
무슨 말씀이신지는 이해가 됩니다만 순수히 컴퓨터를 좀
무슨 말씀이신지는 이해가 됩니다만 순수히 컴퓨터를 좀 더 알고싶은 사람들도 있으니 기왕이면 요즘 CPU의 분기예측이 어떠어떠하니까 이런거에 고민하지 말라거나 컴파일러의 최신 트렌드를 소개하는 등의 댓글을 달아주시면 고맙겠습니다.
Think low-level, write high-level 이라는 말도 있지않습니까?
태클아니니 오해마시기 바랍니다.
생산적인 댓글을 달자
여기에 답글을 달기에는 너무 길구요. 그냥 구글링
여기에 답글을 달기에는 너무 길구요. 그냥 구글링 하셔도 잘 나옵니다.
가볍게 읽어보실만한 서적은 "프로그래머가 몰랐던 멀티코어 cpu이야기"라는 서적을 보시면 요즘 cpu의 기능에 대해서 알기 쉽게 설명되어있습니다.
컴파일러에 대해서는 구글에서 "compiler optimization" 라고만 검색해도 많이 나옵니다.
http://en.wikipedia.org/wiki/Compiler_optimization 를 참고해보시면 괜찮을것 같네요.
Think low-level, write high-level 라는 말에 공감은 합니다만 제가 그정도까지 해야하는지에 대해서는 공감이 안되네요.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.
보통은 성능보단 가독성에 더 좋은 쪽으로 소스를
보통은 성능보단 가독성에 더 좋은 쪽으로 소스를 쓰게되는데
그렇지 않고 이런 고민을 가지고 있다면 그냥 어셈코드를 생성해서 직접 보면 됩니다.
그게 정답이구요.
그냥 말로만 갑론을박 하는건
잘못된 이야기를 진실로 오해하게 만드는 위험이 있습니다.
이말이 정답
이런 건 같은 시스템이라도 컴파일러 버전이나 컴파일 옵션에 따라 달라지기 때문에 직접 해보지 않고서는 알 수 없습니다.
그리고 해봐서 "아 이게 더 빠르구나"라고 최적화를 한다 해도, 어차피 컴파일러 버전이 바뀌면 언제 바뀔지 모르기 때문에 큰 의미가 없습니다.
(A) if( !valueName || !value
(A)
위에서도 열거가 되었듯이 에 의해서 첫번째 조건이 만족하면 2번째와 3번째의 evaluation은 의미가 없기 때문에 그냥 statement를 수행하게 됩니다.
short-circuit evaluation 기능은 컴파일러 optimization의 얘기가 아니라 원래 그렇게 작동하도록 되어 있습니다(컴파일러 전통적인 기능임).
따라서 디버깅 모드에서도 short-circuit evaluation이 적용되게 됩니다.
(B)
(가), (나), (다) 코드가 다르다고 한다면 참 거짓을 연속적으로 판단하는 분기가 이루어 지겠지만,
컴파일러의 최적화에 의해서 (가)(나)(다)가 전부 같은 코드라고 컴파일러가 판단을 해서
컴파일 최적화에 의해서 (B)는 (A)와 동일하게 작동하지 않을까 생각을 해 봅니다.
다만, 이것은 컴파일러마다 다를 수 있으므로 직접 해 보는 수밖에 없다고 봅니다.
www.gilgil.net
많은 분들이
많은 분들이 다양한 의견을 내 주셨네요.
생각의 정리가 된 것 같습니다. 감사합니다
댓글 달기