함수, 생각없이 쓰면 낭패본다.
다중 분기, 루프, 함수는 프로그램 속도를 떨어뜨림. 함수는 분기와 더불어 문맥교환 등 추가적인 비용이 들기 때문에 호출의 깊이가 깊을수록 프로그램 성능에 좋지 않다.
매크로 함수 매크로 함수는 함수 호출에서 발생하는 오버헤드가 발생하지 않는다. 그러나 모든 부분이 코드로 치환되기 때문에 메모리(ROM)의 낭비는 막을 수 없다. #define MUL(x,y) ((x)*(y)) |
매크로 함수 사용시 고려해야 할 사항
- 모든 함수를 매크로화 하면 프로그램의 전체 크기가 커지게 되고, 이는 메모리 사용량을 늘릴 뿐 아니라, 사용하는 캐시에 맞지 않아 속도를 떨어뜨릴 수 있다.
- 매크로 함수의 인자는 매번 계산되므로, 인자의 수식이 복잡하다면 cpu시간을 증가시킨다. 특히 매크로 함수는 코드의 치환이기 때문에 부작용(side-effect)이 발생하기 쉽다.
- 매크로는 컴파일러에 따라 문자수의 제한이 있을 수 있다. 이를 꼭 체크하라.
- 매크로는 한번 사용하면 툴에 의한 디버깅이나 최적화가 힘들다. 사용하기 전에 버그와 최적화를 고려하여, 문제가 없는지 체크한 후에 사용하라.
인라인 함수를 호출하는 대신 함수 코드를 호출 위치에 삽입하는 방법. gcc를 비롯한 대부분의 c컴파일러에서 지원, 높은 레벨의 최적화에서는 작은 크기의 함수를 자동으로 인라인 처리하기도 한다. 분기를 하지 않기 때문에 속도를 높일 수 있지만, 매크로처럼 코드를 직접 삽입하기 때문에 프로그램 크기가 커진다. 비슷한 성능을 보인다.(인자를 복사할 필요가 없으므로 인자 전달과 관련된 오버헤드가 없다.)
__inline int square(int x){ return x * x; }
double add(int x, int y){ return (square (x) + square(y)); }
|
재귀함수
리턴값을 이전 함수로 넘기지 않는거 int fact(int x, int y){ if(x==0) return y; else return fact(x-1,y*x); } 참조 테이블을 이용하여 속도를 빠르게 하는거
int f[] = {1,1,2,6,24,120, ...};
int fact(int x){ return f[x]; } |
인수 전달의 오버헤드를 줄이는 방법 -함수의 인자용으로 할당된 레지스터의 개수 이하로 인수를 넘긴다. 만약 인자의 개수가 그 수를 넘을 경우엔 그만큼 중요하거나, 많은 일을 해야 한다. 즉 불필요하지 않은지, 줄일 수는 없는지 확인한다. -구조체와 같이 큰 크기의 인수를 넘길 경우에는 포인터를 사용한다. -상관성이 있는 인수들은 구조체로 묶어서, 이에 대한 포인터로 넘긴다. 이는 인수의 수를 줄일 뿐 아니라, 가독성을 높인다. -되도록이면 인자의 데이터 타입은 네이티브 데이터 타입을 사용한다. double 처럼 큰 크기를 사용하면, 레지스터를 사용할 수 있는 인자의 수가 줄어든다. |
리프 함수(leaf function)의 활용
리프 함수는 함수내에서 다른 함수를 호출하지 않는 함수를 말한다.