본문 바로가기
개념공부/임베디드 C 프로그래밍 최적화

임베디드 C 프로그래밍 속도 최적화 - 분기문 최적화

by Zach Choi 2024. 7. 14.
728x90
반응형

1. 다중 분기문의 비교문에 공통된 연산이 있다면, 연산 결과를 변수에 저장하여 사용하자.

 아래 코드는 다중 if 분기문이고 각 비교문은 동일한 연산이 반복되는 코드이다. 디스어셈블리 코드 컴파일해 보면, 비교문에 동일한 연산이 반복되는 것을 알 수 있다. 즉, 동일한 연산이 코드 크기를 증가시키고 속도를 떨어뜨리고 있다.

 

 이를 개선하기 위해선, 반복되는 연산을 변수에 저장하여 비교문에서 사용하면 된다. 아래 코드와 같이 반복되는 연산을 미리 계산 후 변수 k에 저장한다. 그리고 비교문에서는 수식이 아닌 변수를 이용한다. 디스 어셈블리 코드를 보면 비교문의 어셈블리 코드 개수가 줄어든 것을 확인할 수 있다.


2. 다중 if 문은 switch 문으로 변경을 고려해보자.

 위에서 개선한 코드는 다중 if 문의 각 비교문에 동일한 연산이 아닌 변수를 사용한 것이다. 이 코드는 좀 더 개선이 가능하다. 다중 if 문을 switch 문으로 변경해보자.

 

 switch 문은 각 case로 분기되기 전, 변수 k의 비교를 1회 수행한다. 이를 다중 if 문의 디스어셈블리코드와 비교해보면, 각 비교문마다 연산이 수행되는 if문과 달리 swtich 문에서는 비교가 1회 수행됨을 알 수 있다. 즉, switch 문으로 변경이 가능한 코드라면 다중 if 문보다 더 빠른 속도의 코드로 개선 가능하다.

 

(하지만 특정 컴파일러는 swtich 문을 다중 if 문의 처리 방식과 동일한 코드로 컴파일링 한다고 하니, 컴파일 후 디스 어셈블리 코드로 비교해보는 과정이 필요하다.)


728x90

3. 다중 if 문을 사용해야 한다면, 이진 분리(Binary Breakdown) 분기를 사용해보자.

 이진 분리란 이진 탐색(Binary Search)과 같은 아이디어의 방법이다. 아래 두 코드를 비교해보자.

 

 좌측의 코드는 총 10개의 비교 및 분기문이 존재한다. 만약, 변수 k 가 1 혹은 2라면 첫번째 / 두번째 비교문에서 분기가 되지만, 10이라면 9번의 비교 연산을 거쳐야 한다.

 

 반면, 우측의 코드는 k를 크기 5를 기준으로 분기한 후, 비교를 수행하므로 총 5번의 비교 연산 만으로 도달 가능하다. 이렇게 이진 분리 분기는 이진 트리 형태로 범위를 설정하여 비교하기 때문에 비교 횟수를 줄여 속도를 높일 수 있다. (이진 탐색과 아이디어가 동일하다.)


4. Switch 문의 입력 인자는 비교 변수와 자료형이 동일해야 한다.

 아래 두 소스코드는 비슷한데, 변수 c와 case 문에 문자를 사용하였는지, 정수를 사용하였는지의 차이가 있다. 각 코드는 수행 속도 면에서 차이가 발생하는데, 그 이유는 getch() 함수의 반환 자료형이 int, 정수이기 때문이다.

 

 좌측 코드의 경우 변수 c는 char 형이다. 반면, getch() 함수는 int 자료형을 반환하기 때문에, 자동 형변환이 발생해 추가적인 연산이 발생한다. 그리고 case 문에서의 비교에서도 형변환이 발생하게 된다.

 

 반면, 우측 코드의 경우 함수의 자료형과 일치되는 값과 비교하기 때문에 형변환이 발생하지 않는다. 따라서 더 빠른 속도의 코드가 된다.

 


참조 : 임베디드 프로그래밍 C 코드 최적화, 김유진 저, 한빛 미디어

728x90
반응형