Presentation is loading. Please wait.

Presentation is loading. Please wait.

C 코드최적화 세명대학교 AI연구실 양승조.

Similar presentations


Presentation on theme: "C 코드최적화 세명대학교 AI연구실 양승조."— Presentation transcript:

1 C 코드최적화 세명대학교 AI연구실 양승조

2 1. 소개 모바일 프로그래밍 PC에서도 메모리의 용량도 높아지고 속도도 더욱 더 빨라지고 있으나 역시 최적화가 필요하다
일정 수준의 품질을 유지하면서 자원을 덜 차지하고 빠른 속도로 처리되는 프로그램을 개발 해야함 PC에서도 메모리의 용량도 높아지고 속도도 더욱 더 빨라지고 있으나 역시 최적화가 필요하다

3 2. 어디에 필요한가? 각각의 모듈 중 어느 모듈이 느리게 작동하는가? 메모리를 많이 차지하는가?를 알아내는 것이 중요하다.
Visual c++ Profiler (함수별 소비시간 측정) 리눅스 gpof, profiler 루프 혹은 third party 라이브러리 매서드를 호출하는 영역

4 3. 정수 사용해야 할 값이 음수를 사용하지 않는다면 unsigned int 를 사용해야 한다. 연산 시간
float > int > unsigned int

5 4. 나눗셈 & 나머지 나눗셈 연산은 피하는 것이 좋다. a/b > c -> a > b*c

6 5. Combining division and remainder
int func_div_and_mod (int a, int b) {         return (a / b) + (a % b);     } 나눗셈 function을 컴파일러에 결합하는 것이 좋다. 나눗셈 function은 항상 나눈값과 나머지를 리턴하기 때문에 나누기와 나머지의 결합

7 6. 2의 배수로 나누기 나누기를 할 때 2의 배수를 분자화 함으로써 효율적으로 만듬
나누기 대신 shift를 할 수 있기 때문 Ex> 66으로 나눠야 한다면 64로 나눌 수 있도록 Shift를 하더라도 signed보다 unsigned가 더 오래걸린다. 부호비트 때문에 연산이 한번 더 들어감

8 7. 배열을 이용한 index 생성 if ( queue == 0 )    letter = 'W'; else if ( queue == 1 )    letter = 'S'; else letter = 'U'; static char *classes="WSU"; letter = classes[queue];

9 8. 나머지 연산자의 대체 uint modulo_func1 (uint count) {    return (++count % 60); } uint modulo_func2 (uint count) {    if (++count >= 60)   count = 0;   return (count); } 위 코드에서 if문이 더욱 빠르다

10 9. 전역 변수 전역 변수의 사용을 줄여야 한다. 전역 변수의 접근을 줄이는 코드 전역 변수는 레지스터에 할당할 수 없다.
int f(void); int g(void); int h(void); int errs; void test1(void) {   errs += f();   errs += g();   errs += h(); } void test2(void) {   int localerrs = errs;   localerrs += f();   localerrs += g();   localerrs += h();   errs = localerrs; } 전역 변수의 사용을 줄여야 한다. 전역 변수는 레지스터에 할당할 수 없다. 전역 변수의 접근을 줄이는 코드

11 10. Using Aliases void func1( int *data )
{       int i;      for(i=0; i<10; i++)      {             anyfunc( *data, i);      }   } void func1( int *data )   {       int i;       int localdata;       localdata = *data;       for(i=0; i<10; i++)       {           anyfunc ( localdata, i);       }   } 위 코드는 변화가 없는 변수임에도 불구하고 루프문을 통해서 계속 접근하고 있다. 지역변수를 써 줌으로써 해결이 가능하다

12 11. 지역 변수 가능하면 char이나 short를 사용하지 않도록 한다.
8비트 혹은 16비트를 할당한 후 남는 비트를 줄이는 작업을 추가로 하기 때문 int wordinc (int a) {    return a + 1; } short shortinc (short a) {     return a + 1; } char charinc (char a) {     return a + 1; } 이렇게 32비트로 연산을 하도록 함수를 만들 필요가 있다. 이것은 RISC의 장점과 일맥상통한다.

13 12. 포인터 구조체를 그대로 넘길 경우 구조체의 모든 값을 넘기지 말고 포인터를 넘길 수 있도록

14 13. Pointer chains typedef struct { int x, y, z; } Point3; typedef struct { Point3 *pos, *direction; } Object; void InitPos1(Object *p) {    p->pos->x = 0;    p->pos->y = 0;    p->pos->z = 0; } 포인터를 사용할 때 여러 번 그 변수에 접근 하지 말고 지역변수에 넣어 놓은 후 접근하면 레지스터나 캐시를 이용하기 때문에 좀 더 효율적으로 작동한다. 코드가 보기 좋다는 이점도 있다. void InitPos2(Object *p) {    Point3 *pos = p->pos;    pos->x = 0;    pos->y = 0;    pos->z = 0; }

15 15. Binary Breakdown if(a==1) { } else if(a==2) { } else if(a==3) { } else if(a==4) { } else if(a==5) { } else if(a==6) { } else if(a==7) { } else if(a==8) { } if(a<=4) {     if(a==1)     {     }  else if(a==2)  {     }  else if(a==3)  {     }  else if(a==4)   {       } } else {     if(a==5)  {     } else if(a==6)   {     } else if(a==7)  {     } else if(a==8)  {     } } 이진 트리와 비슷한 형식으로 비교횟수가 현저하게 떨어진다 필요에 따라서 3중 if문으로 만들 수도 있는데 좀 더 빠르게 작동 하겠지만 코드가 보기 어려워 진다.

16 16. Switch 대신 lookup table 를 사용하라
char * Condition_String1(int condition) {   switch(condition) {      case 0: return "EQ";      case 1: return "NE";      case 2: return "CS";      case 3: return "CC";      case 4: return "MI";      case 5: return "PL";      case 6: return "VS";      case 7: return "VC";      case 8: return "HI";      case 9: return "LS";      case 10: return "GE";           default: return 0;   } } char * Condition_String2(int condition) {    if ((unsigned) condition >= 15) return 0;       return       "EQ\0NE\0CS\0CC\0MI\0PL\0VS\0" +        3 * condition; }

17 17. 루프 많은 경우 루프에서 과다한 시간을 소비하게 된다. 여러번 실행되는 루프틔 특성상 조그마한 시간의 낭비가 게속 누적되기 때문이다.

18 17.1 Loop termination int fact1_func (int n) {     int i, fact = 1;     for (i = 1; i <= n; i++)       fact *= i;     return (fact); } int fact2_func(int n) {     int i, fact = 1;     for (i = n; i != 0; i--)        fact *= i;     return (fact); }

19 17.2 더욱 빠른 for 문 함수는 호출되기 위한 오버헤드가 분명 존재한다. 그래서 반복문안에 함수 호출을 넣는 것보다 함수 안에서 반복문을 쓰는 것이 좋다.

20 17.3 Early loop break 우리는 흔히 루프가 마지막까지 돌지 않아도 되는데 브레이크를 시키지 않는 경우가 많다. 브레이크를 사용해 쓸 데 없는 루프를 없애자.

21 18. 함수 디자인 가능한 인자를 줄여라 인자가 4개를 넘어가면 스택을 통해서 넘기기때문에 그만큼 메모리 접근이 발생한다. 구조체의 포인터를 넘기는 법도 가능하고 좋다. __inline키 워드를 이용하면 일종의 매크로 처럼 작용을 하며, 함수가 호출되는 대신 함수의 본체가 직접 치환이 되어 버린다.


Download ppt "C 코드최적화 세명대학교 AI연구실 양승조."

Similar presentations


Ads by Google