본문 바로가기
대외활동/시스템프로그래밍

컴파일러 최적화

by hoshi03 2024. 7. 23.

 

• 변수별 특성

 

• 재귀함수 최적화

#include <stdio.h>

#if TCASE==1 //재귀
int fact(int n) {
	if((n==1) || (n==0)) return 1;
	else return n * fact(n-1);
}
#elif TCASE==2 //goto로 하는 루프
int fact(int n) {
	int i=1, rst=1;
	if(n==0) return 1;
loop:
	if(i<=n) rst *= i++;
	else return rst;
	goto loop;
}
#elif TCASE==3 // for문
int fact(int n) {
	int i, rst=1;
	if(n==0) return 1;
	for(i=1; i<=n; i++) rst *= i;
	return rst;
}
#endif

int main(void)
{
	fact(5);
	return 0;
}

 

재귀,goto,반복문으로 팩토리얼 연산을 하는 소스코드를 컴파일한 후 디스어셈블해서 비교

 

- 컴파일, 디스어셈블리 명령어

gcc recursiveFunc.c -g -DTCASE=3
objdump -d -S a.out > r3 

재귀  함수는  반복적인  처리를  짧은  코드와  효과적인  처리로  편의를  제공하지만, 함수의  반복적인  호출 은  비용이  많이  들며  이전  계산  결과가  필요한  재귀  함수는  성능이 낮은 걸 알 수 있다

 

 

• 함수 인자 최적화

 

• 비용이 낮은 연산자 선택

% 연산보다는 & 연산을, / 연산보다는 >> 연산을 하는게 좋다

#include <stdio.h>

int main(void)
{
	int d1, d2, d3, d4;
	
	d1 = 51;  d2 = 51;
	d1 %= 8;
	d2 &= 7;
	printf("d1:%d, d2:%d\n", d1, d2);
	
	d3 = 31;  d4 = 31;
	d3 /= 4;
	d4 >>= 2;
	printf("d3:%d, d4:%d\n", d3, d4);
	
	return 0;
}

 

• short circuit 원리

 

&& 조건은 앞이 거짓이면 뒤 실행 X

|| 조건은 앞이 참이면 뒤 실행 X

&& - 논리곱은  거짓일  확률이  높은  문장을  앞쪽에  둠 

|| - 논리합은  참일  확률이  높은  문장을  앞쪽에  둠

 

• 연관된 표현의 묶음 처리

나눗셈 연산을 묶는건 묶음 처리로 적절하지만

스위치 문을 비트연산으로 변환한 경우는 가독성이 크게 떨어져버린다

적절하게 묶음 처리하자

 

• 프로파일링 활용 최적화

time 유틸리티

clock() 함수

- gprof 유틸리티 프로파일링 예제

#include <stdio.h>
#include <stdlib.h>

int prime(int num);

int main(void)
{
	int i;
	
	int colcnt = 0;
	for(i=2; i<=50000; i++) {
		if(prime(i)) {
			colcnt++;
			if(colcnt%9 == 0) {
				printf("%05d\n", i);
				colcnt = 0;
			} else {
				printf("%05d ", i);
			}
		}
	}
	putchar('\n');
	
	return 0;
}

int prime(int num)
{
	int i;
	for(i=2; i<num; i++) {
		if(num%i == 0) return;
	}
	return 1;
}

 

cc -pg -o profile profileTest.c

./profile

gprof -b ./profile