if else 보다 ? : 연산이 더 오래 걸리는 이유는?
글쓴이: sangheon / 작성시간: 수, 2006/11/29 - 1:36오후
하나는 if else를 하나는 ? : 연산을 사용한 소스입니다. 둘 다 어셈블리어로 바꿔놓으니 ? : 을 사용한 경우 어셈블리어 명령 두개를 더 실행하는군요.
단순한 구조라 같은 결과를 낼 것으로 생각했고 만약 어느 하나가 더 짧다고 하면 ? : 연산자 쪽이라고 생각했는데 결과는 정반대입니다.
왜 이렇게 되는지 알고 싶습니다. (컴파일은 -O0 으로 했습니다.)
int main(void) { int a = 0, b = 1, c = 2; if (a > b) c = 1; else c = 2; return c; }
.file "c.c" .text .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $16, %esp movl $0, -16(%ebp) movl $1, -12(%ebp) movl $2, -8(%ebp) movl -16(%ebp), %eax cmpl -12(%ebp), %eax jle .L2 movl $1, -8(%ebp) jmp .L4 .L2: movl $2, -8(%ebp) .L4: movl -8(%ebp), %eax addl $16, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.1 (Gentoo 4.1.1-r1)" .section .note.GNU-stack,"",@progbits
int main(void) { int a = 0, b = 1, c = 2; return c = (a > b) ? 1 : 2; }
.file "d.c" .text .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $20, %esp movl $0, -16(%ebp) movl $1, -12(%ebp) movl $2, -8(%ebp) movl -16(%ebp), %eax cmpl -12(%ebp), %eax jle .L2 movl $1, -24(%ebp) jmp .L4 .L2: movl $2, -24(%ebp) .L4: movl -24(%ebp), %eax movl %eax, -8(%ebp) movl -8(%ebp), %eax addl $20, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.1 (Gentoo 4.1.1-r1)" .section .note.GNU-stack,"",@progbits
Forums:
제가 생각하기에도
제가 생각하기에도 최소한 둘이 같아야 할 것 같은데요.
혹시 밑에 소스에서
로 해도 결과가 같은가요?
최적화가 없다면 둘이 약간 다른 의미일 수도 있을것 같아서요.
c코드를 어셈블리로 바꾸는 방법을 몰라서요..
ㅡ,.ㅡ
죄송합니다.
답이 아니라 질문이 되었네요.
-- Signature --
青い空大好き。
蒼井ソラもっと好き。
파란 하늘 너무 좋아.
아오이 소라 더좋아.
c = ( a > b ) ? 1 :
어셈코드를 보시면 -24(%ebp) 라는 임시저장소가 사용된 것을 보실 수 있습니다.
일단 여기에 담아놓고 다시 -8(%ebp) 로 옮기죠.
질문하신 if 와 ?: 는 동일합니다.
"? :"는 연산자이기
"? :"는 연산자이기 때문에 하나의 덩어리로 취급하기에 이렇게 된 걸로 보입니다. (a>b)? 1 : 2; 에 포함된 1 과 2를 개별적으로 취급하지 않는 거죠.
지금의 이런 결과 때문에 "? :" 연산이 비효율적이다라고 단정지을수는 없겠지요. 어디까지나 -O0 옵션을 주었을때 컴파일러의 해석결과일 뿐입니다.
Compiler 설계상의 차이입니다.
if-else에 대한 설계와 ?:에 대한 설계 상의 차이입니다.
윗 분 말씀대로 "? :"는 연산자이기 때문에 해당 연산자를 어떻게 처리할 것인지는 compiler를 설계한 사람의 몫입니다. 요컨데, ANSI에서는 특정 연산자가 어떤 기능을 수행해야 한다는 것만을 정의할 뿐 이를 어떤 방식을 이용해 구현할 것인지는 compiler 설계자의 몫이기에 compiler에 따라 세부적인 처리 방식은 모두 다르다는 것입니다. 이 경우 if-else에 대한 처리와 ?:에 대한 처리가 다르게 설계되어 있고(당연하지만...) ?:에 대한 처리가 if-else에 대한 처리보다 좀 더 performance가 떨어지는 기계어 코드가 생성되도록 설계된 것으로 보입니다. 이는 compiler 종류에 따라 모두 다릅니다.
예를 들어, 논리적으로 동일한 코드이지만 연산자를 사용한쪽이 gcc에서는 2번의 operation을 더 수행하는 반면, Visual C에서 서로 다른 기계어 코드를 생성하면서도 총 operation의 개수는 동일하게 생성되어 두 코드 모두 거의 동일한 performance를 기대할 수 있는 코드를 생성하였습니다.
올려주신 disassemble된 코드를 살펴보면 gcc의 경우 ?: 연산자를 처리할 때 조건에 부합하여 assign될 값을 stack에 저장하도록 설계가 되어 있습니다. 이 부분에서 processor의 특성상(Intel이시죠?) 메모리에서 메모리로 move가 되지 않기 때문에 stack에 저장된 값을 레지스터 eax에 옮겼다가 이를 다시 stack에 저장된 local 변수 c에 저장을 하고 있습니다. 이 부분에서 불필요하다고 할 수 있는 추가적인 operation이 생성되었죠. 그 후 C 함수가 return 값을 레지스터 eax를 이용해 반환하기 때문에 stack에 저장된 변수 c의 값을 다시 eax에 옮기고 있습니다.
return c = (a > b) ? 1 : 2;
대신에
return (a > b) ? 1 : 2;
라고 코딩을하게 되면 아래 주석처리한 2개의 operation이 생성되지 않아 동등한 performance를 가질 수 있으리라 예상됩니다.
.L4:
movl -24(%ebp), %eax
# movl %eax, -8(%ebp)
# movl -8(%ebp), %eax
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
자세한 답변
자세한 답변 감사합니다. ^^b
B/o/o/k/w/o/r/m/
--
Minimalist Programmer
int main(void) { int
int main(void)
{
int a = 0, b = 1, c = 2;
if (a > b)
c = 1;
else
c = 2;
return c;
}
int main(void)
{
int a = 0, b = 1, c = 2;
return c = (a > b) ? 1 : 2;
}
그런비교하는거라면 두코드는 좀다르다고보는데요.
같게 하려면..
int main(void)
{
int a = 0, b = 1, c = 2;
(a > b)? c = 1 : c = 2;
return c;
}
이렇게 되어야 죠..
----------------------------------------------------------------------------
시험 목적이 소스
시험 목적이 소스 코드 크기의 버밍이 실제 오브젝트 코드의 감소로 이어지는지를 확인해보려는 것이었구요. 그래서 그래서 동일한 효과를 가지지만 최대한 코드 크기를 절약하는 코드를 만들어 본게 두번째 코드입니다. ^_^
이번 예로 소스 코드의 길이와 오브젝트 코드의 길이는 정반대인 경우도 있다는 것을 알 수 있었습니다.
B/o/o/k/w/o/r/m/
--
Minimalist Programmer
아, 아래 코드는
아, 아래 코드는 리턴값을 가지는 함수로 해석될 가능성이 높겠네요.
아닌가요? ㅋㅋ
ㅡ,.ㅡ;; 님께서 말씀하신게 더 정확할 것 같습니다.
c언어 마음은 항상 가지만 언제 다시 해보게 될라나..
지금 하시는 분들 보면 많이 부럽습니다.
-- Signature --
青い空大好き。
蒼井ソラもっと好き。
파란 하늘 너무 좋아.
아오이 소라 더좋아.
댓글 달기