굿 모닝 에브리 바디 ㅋㅋ

날씨가 굉장히 춥군요 ㅋ

여친님이 모닝콜 안했으면 아조 그냥 저세상 갈때까지 잠만 잘뻔했네 ㅋㅋ

오늘의 주제는 if 문과 switch 문의 최적화 입니다.

if 문과 switch 문의 차이점은 다 아시지요???

간단하게 한번 집고 넘어가자면,

다중 if 문을 쓸경우 (if, else if, else if ...... , else) 순차적으로 조건을 모두 비교해나가고,
switch 문은 비교 변수 인자와 비교를 해서 해당되는 case 로 바로 분기한다.


이해가 되실려나?? 

아 이게 안좋은 점이야 ㅋㅋ 분명히 최적화 글을 읽으려고 오신분 들은 저 정도 차이는 아실텐데 자꾸 자세히 쓰게되네 ㅠㅠ

Psudo Code 로 잠시 표현을 해보지요 

if(a==1)
else if(a==2)
else if(a==3)
....
else

와 같이 썼다고 가정해보지요. a == 100 까지 있다고 치공 ㅋㅋ

a ==99 가 들어왔어요 ㅋㅋ

그럼 바로  else if (a==99) 로 가지를 못하고, a==1 이였나??/ 거짓 ! 그럼 a==2야?? 아니 ㅋㅋ

이러면서 99 가 나올때까지 계속 비교를 한다는 것이지요 ㅋㅋ

하지만!!!

 switch 문은 a ==99 가 들어오면 99번에 해당하는 케이스로 바로 분기를 해 간다는 소리입니다.

즉! 차이점은?? 비교를 여러번 하느냐 한번만 하느냐의 차이라고 볼수 있습니다.

근데 여기서 하려고 했던 이야기는 이런것이 아니고 ㅋㅋㅋ

부득이 하게 위와 같은 다중 if 문을 쓸 경우에는 다중 분리 분기문을 이용해서 사용하면 오버헤드를 줄일수있습니다. 

예를 볼까요???

if(a==1)
else if(a==2)
....
else if(a==8)

과 같이 짜진 코드를 이진 분리해보면

if(a<=4)
{
if (a==1)
...
else if(a==4)
}
else
{
else if(a==5)
....
else if (a==8)
}
 
이런 식으로 짜면 확실히 비교의 횟수가 줄어들었지요????

switch 문 같은경우도 좀더 효율적으로 사용하기 위해서는

비교 인자를 문자로 사용할 때 보다 바로 숫자로 사용할때가 훨씬 좋습니다. 문자로 사용할때는 컴파일러가 형변환을 하게 되어서 시간이 조금 더 걸리거등여 ㅋㅋ

그리고 확률적으로 자주 사용될수 있는 케이스를 앞쪽에 위치시켜 주는 것도 한 방법이라 할 수 있겠습니다.
이것은 if 문에도 적용되는 이야기 입니다.

정리해 볼까용?

(1) 다중 분기문의 비교문에서 사용하는 연산은 한번만 수행하고, 이를 변수에 저장하여 사용한다.
(2) if 문 보다는 switch문이 속도, 메모리 적인 측면에서 모두 효율적이다.
(3) if 문으로 표현해야 한다면 선택될 확률이 높은 비교문을 앞쪽에 위치시기고, 이진 분리 분기 등과 같이 비교문의 실행을 줄이는 방법을 모색하도록 한다.
(4) 비교문과 같이 반복적으로 사용되는 데이터의 데이터 타입을 잘 선택한다.

등으로 정리 할 수 있겠군요.

이것 또한 자투리 지식으로 알아 둔다면 나중에 아는 척 하기 딱 좋겠지요? ㅋㅋㅋ

그럼 바이바바이
 
 
저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by J.Bear
제목이 이상한가??

ㅋㅋㅋ

어차피 이 글을 클릭하시는 분들은 C에대해 어느정도 자신감이 붙으신 분들이실테고 ㅋㅋㅋ

근데 ! 연산자와 ~연산자의 정확한 차이를 알고 계신감용???

헷갈리시는 분들 많으실겁니다 ㅋㅋㅋ

(1) ! 연산자

Logic NOT 입니다.
C 언어에서는 0 이 아닌 모든 수는 다 1로 생각하죠 ㅋㅋ LOGIC 적으로 말이에요 ㅋㅋ

단편적인 예로 if(3) 이렇게 써도 무조건 참으로 알고 돌자나영 ㅋ

! 연산자는 이렇듯 로직을 바꾸어주는 역할을 한답니다.

값을 바꾸는것이 아니라요 ㅋㅋ

예는 ~ 연산자와 함께 보여드리지요

(2) ~ 연산자

Bit Value NOT 입니다.

이해가 되시나영??

모든 수는 2진수로 저장됨은 알고 계시겠지요?/

각각의 비트에 들어갈수 있는 값은 1 아니면 0 입니다.

이 각각의 비트의 값을 반대로 바꾸는 것입니다.
 

(예제) 

 int main(void)
{
volatile unsigned int test_a = 10;
test_a = !test_a;


test_a =  ~test_a ;
}

(이해를 돕기 위해서 unsigned int 로했습니다. signed 로하면 부호가 바뀌겠지요?)

아래는 정답입니다.

 


아시겠지요????


여기서 제가 원래 이야기 하고 싶었던 부분은

LOGIC NOT 연산자의 최적화 입니다.

도대체 뭘 최적화 한다는 것이냐??

로직을 바꾸는데 ! 연산자를 쓸수도 있지만 ^ 연산자를 쓸수도 있습니다.
Exclusive OR 연산자 이지요~


1과 XOR 를 계속해주면 1,0,1,0 순서로 값이 반전됩니다.

과연 어떤 연산자를 써서 LOGIC NOT 을 하는 것이 더 빠를까요? ㅋㅋㅋ

일단 정답을 XOR 입니다 ㅋㅋ

아래는 비교하기 위한 코드이고 그 아래에서 어셈코드 보시죠 

int main(void)

{


volatile unsigned int test_a = 1;

test_a = !test_a;

test_a ^= 1;



[##_http://jbear.tistory.com/script/powerEditor/pages/1C%7Ccfile7.uf@196544404F0CE9551E0090.PNG%7Cwidth=%22363%22%20height=%22263%22%20alt=%22%22%20filename=%22dddddd.PNG%22%20filemime=%22image/jpeg%22%7C_##]

 역어셈 코드 잠시 알아볼까요??

MOVS(r4,#0x01) : r4 레지스터 1을 집어넣었군요

CBNZ : 0이거나 0이 아닌경우 비교 분기 (r4 는 피연산자가 들어가는 레지스터, 분기할 주소)
MOVS : r4 에 있던 값을  r0 레지스터로 옮기넹??
B : 다시 분기를 하는군요 0x080004C0 로 ㅋㅋ
MOVS : r0 에 0을 이동시켜놓고
MOV : r4 에다가 변화된 r0 를 이동시켜 놓으면서 ! 연산자 수행이 끝납니다

총 5개의 Instruction Set 을 돌았네용

아래는 ^ 연산자군요 ㅋㅋ

걍 EOR 하나죠? ㅋㅋ Exclusive OR 명령어 SET 을 가지고 있나바여 ㅋㅋ

아 참, 이 컴파일러는 uVision4 를 사용했습니다
Target CPU 는  ST 사에서 CortexM3 코어로 만든 STM32F103ZG 입니다

여튼 1개의 명령어로 끝나는군요 ㅋㅋ 

수행시간 차이를 볼까요??



! 연산자 : 4ns
^ 연산자 : 2ns

약 2배정도 차이가 나는군요~

물론 엄청 작은시간입니다 ㅋ 하지만 이런게 있다는것을 알아두는 것이 나쁘지는 않을듯 싶네요


저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by J.Bear