9-3-마.미리 계산된 값

다음 예제는 지구가 태양을 공전하는 동작을 시뮬레이션하는데 그래픽 환경이 아니기 때문에 다소 썰렁해 보이기는 하지만 좌표 계산은 제대로 하고 있다. 실행해 보면 태양을 상징하는 S 주위를 지구 E가 끊임없이 원 운동을 하는데 그래픽 환경이라면 실감나는 동영상을 감상해 볼 수 있을 것이다.

 

: Revolution1

#include <Turboc.h>

#include <math.h>

 

void main()

{

     double angle;

     int x=-1,y=-1;

 

     clrscr();

     gotoxy(40,12);

     putch('S');

     for (angle=0;;angle+=10) {

          if (angle==360) angle=10;

          if (kbhit()) break;

          gotoxy(40+x,12+y);putch(' ');

          x=int(cos(angle*3.1416/180)*20);

          y=int(sin(angle*3.1416/180)*10);

          gotoxy(40+x,12+y);putch('E');

          delay(100);

     }

}

 

이 프로그램을 작성하려면 매 각도마다 원주상의 좌표를 계산해야 하는데 이때는 삼각 함수가 필요하다. 반지름 r인 원에서 임의의 각도 θ인 원주상의 x, y를 계산하는 공식은 다음과 같다.

이 공식대로 지구의 x, y 좌표를 구하되 sin, cos 함수가 각도가 아닌 라디안을 요구하므로 각도를 라디안으로 변환했으며 콘솔 환경의 좌표가 세로쪽이 길기 때문에 가로 반지름을 세로보다 두 배로 주어 정원이 되도록 했다. 아뭏든 이 공식대로 angle에 대한 좌표를 구하고 angle을 0~350까지 반복적으로 루프를 돌리면 지구를 공전시킬 수 있다.

문제는 이 좌표를 계산하는데 시간이 너무 오래 걸린다는 점이다. 삼각 함수는 실수 차원에서 계산을 하므로 무척 느린데다 라디안을 각도로 변환하는 수식과 실수를 다시 정수로 바꾸는 캐스트 연산까지 꽤 많은 것들을 계산해야 좌표값 하나를 얻을 수 있다. 그나마 지구가 정원 운동을 하기 때문에 공식 하나로 좌표를 구할 수 있지만 만약 아주 복잡한 곡선 운동을 한다면 수식이 더욱 복잡해질 것이다.

이런 복잡한 값을 실행중에 일일이 구해서 사용하면 프로그램의 속도는 그만큼 느려지게 된다. 이럴 때는 필요한 모든 값을 미리 구해 배열에 넣어 두고 배열의 값을 참조하는 방법을 사용할 수 있다. 다음이 배열로 수정해 본 예제인데 결과는 완전히 동일하다.

 

: Revolution2

#include <Turboc.h>

#include <math.h>

 

void main()

{

     double angle;

     int x=-1,y=-1;

     static int arx[]={20,19,18,17,15,12,9,6,3,0,-3,-6,

          -10,-12,-15,-17,-18,-19,-19,-19,-18,-17,-15,-12,

          -9,-6,-3,0,3,6,10,12,15,17,18,19};

     static int ary[]={0,1,3,5,6,7,8,9,9,9,9,9,

          8,7,6,4,3,1,0,-1,-3,-5,-6,-7,

          -8,-9,-9,-9,-9,-9,-8,-7,-6,-4,-3,-1};

 

     clrscr();

     gotoxy(40,12);

     putch('S');

     for (angle=0;;angle+=10) {

          if (angle==360) angle=10;

          if (kbhit()) break;

          gotoxy(40+x,12+y);putch(' ');

          x=arx[(int)angle/10];

          y=ary[(int)angle/10];

          gotoxy(40+x,12+y);putch('E');

          delay(100);

     }

}

 

arx, ary배열에 각도에 해당하는 좌표값을 미리 구해 적어 놓았다. 이 배열의 실제값은 앞 예제가 구하는 x, y를 printf로 출력하면 쉽게 구할 수 있다. 배열에 값을 미리 다 계산해 놓았으므로 실제 이 값이 필요할 때는 몇 번째 값이 필요하다는 요청만 하면 된다. 배열에 있는 값을 읽는 것은 직접 수식을 계산하는 것보다 훨씬 더 빠르므로 프로그램의 전체적인 속도는 비약적으로 향상된다.

배열을 통한 이런 최적화 기법은 아주 기초적인 성능향상 방법중 하나인데 프로그램의 크기가 커지는 대신 속도를 얻는 작전이다. 즉 배열에 미리 계산된 값은 속도에 유리하고 크기에 불리한 방법인데 요즘의 컴퓨터 환경은 메모리가 넉넉하기 때문에 얼마든지 이런 방법을 사용해도 별 무리가 없다. 이런 최적화 기법을 사용하는 실제 예는 스타크래프트라는 게임에서도 볼 수 있다.

캐리어에서 발사되는 요격기인 인터셉터는 굉장히 복잡한 곡선 운동을 하는데 인터셉터의 이동 경로를 실시간으로 계산하는데는 다소 복잡한 수식이 동원될 것이다. 게다가 이런 인터셉터가 한꺼번에 수십개씩 나올 수 있기 때문에 각 인터셉터의 좌표를 일일이 계산해서 사용한다는 것은 무리다. 이럴 때 인터셉터와 캐리어의 상대적인 좌표를 미리 배열에 작성해 놓고 하나씩 꺼내 쓰는 방법을 사용하면 속도상의 많은 이득을 볼 수 있다.