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

임베디드 C 프로그래밍 속도 최적화 - 변수 사용 최적화

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

1. 적절한 데이터 타입 선택이 중요하다.

 임베디드 환경에서 프로세서는 가장 잘 다룰 수 있는 데이터 타입이 있는데 이를 네이티브 데이터 타입이라고 한다. 네이티브 데이터 타입은 해당 프로세서의 한 워드의 크기이다. 한 워드의 크기는 레지스터 크기와 같고 데이터 버스의 폭과 같다. 이는 어셈블리 레벨에서, 네이티브 데이터 타입을 사용하면 가장 적은 인스트럭션이 사용됨을 의미한다. 따라서 코드 크기가 줄어들고 속도 또한 빨라지게 된다.

 

 예를 들자면, 32bit 프로세서의 경우 워드의 크기 = 레지스터의 크기 = 데이터 버스의 폭은 4 byte이다. 이때 double 자료형 변수를 읽어오려면 8 byte이므로 두번의 메모리 엑세스가 필요하다. 자연스레 속도는 감소하는 것이다.

 

 그렇다면 4 byte 보다 작은 크기의 데이터를 읽을 때는 어떨까? 이때는 4byte를 읽어온 후, 유호햔 데이터만 추려내는데 연산이 사용된다.(마스킹 연산) 따라서 이 또한 속도는 감소한다.

 

 따라서 임베디드 코드에서는 프로세서의 네이티드 데이터 타입을 활용하는 것이 중요하다.

728x90

2. 전역 변수 최적화

 전역 변수는 데이터 영역에 저장된다. 반면, 지역 변수는 스택 영역에 저장된다. 스택 영역은 메모리 엑세스 속도가 빠른 편이지만 데이터 영역의 접근은 느리다. 따라서 함수 외부에 선언된 전역 변수를 사용하면, 데이터 영역의 메모리 엑세스가 일어나게 된다. 데이터 영역의 메모리 엑세스 속도는 스택 영역의 속도보다 느리다. 따라서 전역 변수를 사용하지 말고 지역변 수로 복사해서 사용하면 속도를 높일 수 있다.

 

 아래 코드를 통해 확인해보자. foo() 함수는 글로벌 변수에 직접 접근해 값을 수정한다. (데이터 영역으로 메모리 엑세스가 발생한다.) boo() 함수는 전역변수 값을 지역변수로 복사한 후, 지역변수의 값을 수정하고 이를 전역 변수에 저장해준다. (데이터 영역 메모리 엑세스는 2번 발생한다.)

#include <stdio.h>
#include <time.h>

int global_var;

void foo() {
	for (int i = 0; i < 10000000; ++i)
	{
		++global_var;
	}
}

void boo() {
	int local_var = global_var;
	for (int i = 0; i < 10000000; ++i)
	{
		++global_var;
	}
	global_var = local_var;
}

void main() {
	
	double start, end;


	start = (double)clock() / CLOCKS_PER_SEC;
	foo();
	end = (((double)clock()) / CLOCKS_PER_SEC);
	printf("전역 변수 사용 시 수행 시간 :%lf\n", (end - start));


	start = (double)clock() / CLOCKS_PER_SEC;
	boo();
	end = (((double)clock()) / CLOCKS_PER_SEC);
	printf("지역 변수 사용 시 수행 시간 :%lf\n", (end - start));
}

 

 for 반복문을 천만번 수행한 결과, 전역변수에 반복적으로 접근한 foo() 함수의 수행 시간은 0.011 s, 지역 변수를 사용한 boo() 함수는 0.007 s 이다. 전역 변수에 반복적으로 접근하는 것이 속도가 느린 것을 확인할 수 있다.


 

728x90
반응형