본문 바로가기

개념공부/임베디드 C 프로그래밍 최적화8

임베디드 C 프로그래밍 최적화 임베디드 C 프로그래밍 최적화란 CPU, 메모리 등 가용 자원이 제한적인 임베디드 환경에선 코드 최적화가 필수적이다. 코드 최적화는 속도, 메모리, 가독성 등의 요소를 최대화 하는 것을 의미한다. 각 최적화 요소는 trade-off 관계이기 때문에, 일반적으로 모든 요소의 향상을 추구할 수는 없다. 프로젝트 목표나 임베디드 환경에 따라 다른 요소의 성능은 포기하면서, 원하는 성능을 달성해야 한다. (하지만 문제에 따라 특정 알고리즘을 사용해 속도와 메모리의 성능을 모두 끌어올릴 수도 있다.)  임베디드 C 프로그래밍에서 최적화 여부를 확인하는 기초적인 방법인 디스어셈블리 코드를 확인하는 것이다. 디스어셈블리 코드란 우리가 작성한 코수준 코드를 기계어로 변경하기 이전에, 컴파일러가 어셈블리 코드로 만든 것.. 2024. 7. 16.
임베디드 C 프로그래밍 속도 최적화 - 기타 방법들 1. 실수의 나누기는 곱의 형태로 바꾸어 보자. 실수의 나누기 연산은 더하기, 곱하기 연산에 비해 두배 이상 느릴 수 있다. 그래서 나누기 연산을 상수를 이용한 곱 연산으로 바꾸는 것이 좋다. 상수의 연산인 컴파일 시 계산되므로 아래 코드의 (1.0 / 4.0)은 런타임 이전에 처리된다.//before 최적화x = x / 4.0;// After 최적화x = x * (1.0 / 4.0) 참조 : 임베디드 프로그래밍 C 코드 최적화, 김유진 저, 한빛미디어 2024. 7. 16.
임베디드 C 프로그래밍 속도 최적화 - 반복문 최적화 2 1. 루프 변수에 네이티브 데이터 타입을 사용하자. 네이티브 데이터 타입을 사용하면 데이터 버스와 메모리의 접근성이 좋아져 빠르게 동작할 수 있다. (네이티브 데이터 타입이란 프로세서의 한 워드의 크기 = 데이터 버스의 크기이다.) 반복문 제어에 사용되는 변수는 자주 사용되므로 네이티브 데이터 타입을 사용하면 성능을 높일 수 있다.  예를 들어 32bit 마이크로프로세서의 경우, 네이티브 데이터 타입은 int (32bit)이다. int 형 중에서도 부호를 사용하지 않는 unsigned int가 더 빠르기 때문에 반복문의 제어 변수로 unsigned int를 사용하는 것이 좋다. 2. 함수와 반복문의 위치 함수를 호출하면 자원이 사용된다. 분기 명령, 필요한 값들 스택에 저장 등등. 반복문에서 함수를 호출.. 2024. 7. 16.
임베디드 C 프로그래밍 속도 최적화 - 반복문 최적화 1 1. 루프 풀기 아래 2가지 형태의 for 문을 비교해보자. 아래 코드는 크기가 100인 배열에 값을 저장하는 코드이다. 첫번째 for 반복문은 일반적인 반복문이고 두번째 반복문은 루프 풀기를 적용한 것이다.  두 코드 모두 크기가 100인 배열에 값을 저장하지만, 첫번째 코드는 비교 연산 101회, 반복을 위한 계산은 100회를 계산한다. 두번째 코드의 경우 비교 연산은 26회, 반복을 위한 계산은 25회 수행된다. 따라서 루프를 돌리는데 발생하는 비용이 1/4로 줄어들게 된다.  하지만, 그렇다고 루프를 완전히 푸는 것이 최고의 최적화는 아니다. 그만큼 코드 블록이커져 메모리가 커지기 때문이다. 따라서 속도와 메모리 사이에서 적절한 선택이 필요하다. 2. 루프 병합 병합 가능한 인접 반복문은 하나로 .. 2024. 7. 15.
임베디드 C 프로그래밍 속도 최적화 - 분기문 최적화 1. 다중 분기문의 비교문에 공통된 연산이 있다면, 연산 결과를 변수에 저장하여 사용하자. 아래 코드는 다중 if 분기문이고 각 비교문은 동일한 연산이 반복되는 코드이다. 디스어셈블리 코드 컴파일해 보면, 비교문에 동일한 연산이 반복되는 것을 알 수 있다. 즉, 동일한 연산이 코드 크기를 증가시키고 속도를 떨어뜨리고 있다.  이를 개선하기 위해선, 반복되는 연산을 변수에 저장하여 비교문에서 사용하면 된다. 아래 코드와 같이 반복되는 연산을 미리 계산 후 변수 k에 저장한다. 그리고 비교문에서는 수식이 아닌 변수를 이용한다. 디스 어셈블리 코드를 보면 비교문의 어셈블리 코드 개수가 줄어든 것을 확인할 수 있다.2. 다중 if 문은 switch 문으로 변경을 고려해보자. 위에서 개선한 코드는 다중 if 문의.. 2024. 7. 14.
임베디드 C 프로그래밍 속도 최적화 - 변수 사용 최적화 1. 적절한 데이터 타입 선택이 중요하다. 임베디드 환경에서 프로세서는 가장 잘 다룰 수 있는 데이터 타입이 있는데 이를 네이티브 데이터 타입이라고 한다. 네이티브 데이터 타입은 해당 프로세서의 한 워드의 크기이다. 한 워드의 크기는 레지스터 크기와 같고 데이터 버스의 폭과 같다. 이는 어셈블리 레벨에서, 네이티브 데이터 타입을 사용하면 가장 적은 인스트럭션이 사용됨을 의미한다. 따라서 코드 크기가 줄어들고 속도 또한 빨라지게 된다.  예를 들자면, 32bit 프로세서의 경우 워드의 크기 = 레지스터의 크기 = 데이터 버스의 폭은 4 byte이다. 이때 double 자료형 변수를 읽어오려면 8 byte이므로 두번의 메모리 엑세스가 필요하다. 자연스레 속도는 감소하는 것이다.  그렇다면 4 byte 보다 .. 2024. 7. 11.