본문 바로가기
MCU 일반

마이크로프로세서와 실수 연산

by irmus 2008. 10. 18.

마이크로프로세서에서의 실수 연산에 대해 잠깐 살펴보자.
꼭 Cortex-M3에만 적용되는 것이 아니라 모든 마이크로프로세서에 적용 될 내용이다.

intel 387DX math coprocessor

intel 387DX math coprocessor


정수 연산은 간단하다. CPU에서 아주 빠르게 처리할 수 있다. 그렇지만 실수 연산은 그렇게 간단하지가 않다. 그래서 요즘 PC의 CPU에는 별도의 실수 연산기 하드웨어가 포함되어있다. 참고로 386 시절까지만 해도 CPU에 이 실수 연산기가 없었기 때문에 별도의 math coprocessor를 사서 메인보드에 끼워 써야 했었다. 그런데 마이크로프로세서에는 요즘에도 실수 연산기가 안들어있는 경우가 대부분이다. 마이크로프로세서가 아니라 꽤나 성능좋은 ARM9 CPU에도 없는 경우가 많다. 실수 연산기 하드웨어는 비싸고, 웨이퍼 면적이나 전력도 많이 잡아먹는 녀석이기 때문이다.

그러면 이처럼 실수 연산기가 없는 CPU에서는 float나 double 같은 데이터 형을 쓸 수 없는것인가? 하면 또 그렇지 않다. 이가 없으면 잇몸으로 씹는다고, 하드웨어가 없으니 소프트웨어적으로 실수 연산을 처리한다. 이 과정은 똑똑한 컴파일러가 알아서 다 해주기 때문에 프로그램 개발자는 자신의 CPU에 실수 연산기가 있는지 없는지 전혀 신경쓰지 않아도 된다.

그런에 이 말은 절반만 맞다고 해야 할 것이다. 하드웨어적으로 실수 연산을 해 주는 경우와 이를 소프트웨적으로 처리하는 경우는 분명 차이가 있다. 엄청난 속도 차이 말이다. 당연히 하드웨어적인 실수 연산기를 사용하는 경우가 훨씬 더 빠르다.

예전에 실수와 정수 연산 속도를 비교해 보는 간단한 실험을 한 적이 있었는데, 다음 링크를 잠깐 살펴보자.
휴대용 게임기 NDS는 실수 연산기가 없는 ARM9 코어를 사용하고 있다. 메인 클럭은 67MHz. 실험1과 실험3을 비교해 보면 덧셈에 있어 실수 연산이 정수 연산에 비해 60배 가량 느리다는 것을 알 수 있다.
더불어 정수 덧셈은 1클럭, 정수 곱셈은 4클럭 정도를 사용하는 것을 알 수 있다. 그러니 실수 덧셈이나 곱셈은 대략 60클럭정도를 사용하는 샘이다.

myCortex 시리즈에서 사용하고 있는 Luminary micro의 Stellaris 칩셋에도 실수 연산기가 들어있지 않다. Stellaris 칩셋은 Cortex-M3 아키텍쳐를 이용하고 있고, 이는 ARM9과 비슷한 아키텍쳐이다. 따라서 각 연산에 소요되는 시간은 비슷하다고 생각할 수 있으니 저 실험 결과가 거의 비슷하게 적용된다고 볼 수 있을 것이다.

만약 아주 빠르게 동작하는 시스템을 만들고 있다면 어떤 코드가 얼마나 많은 클럭을 잡아먹는지 머리속에서 대충이나마 그림을 그려가면서 디자인 해야 한다. 예를 들어 메인 클럭이 50MHz일때 10KHz의 컨트롤 루프를 가지는 PID 모터 제어 시스템을 만든다면 1 루프는 겨우 5000 클럭밖에 안된다. 정수 덧셈만 한다면 5000번, 실수 곱셈을 한다면 100번도 하지 못하는 시간이다. 이런 시스템에서 아무 생각없이 실수 연산을 썼다가는 머리가 하얗게 새는 경험을 할 수 있다. 그래도 Stellaris는 50MHz나 되기라도 하지, AVR이나 PIC으로는 꿈도 못꿀 일이다.


마이크로프로세서에서 실수 연산을 사용할 때 또한가지 염두에 둬야 하는 것이 있다. 바로 실수 표현. PC에서처럼 printf()함수가 잘 되어 있는 경우가 거의 없기 때문이다. printf()에서 %f를 지원하지 않는 것은 이것 자체가 실수 연산이 되기 때문이다. 속도 때문에 도저히 쓸 수 없는 샘.


이러저러한 이유로 마이크로프로세서에서는 실수 연산을 잘 하지 않는다. 정수로 치환해서 연산하는 방식을 많이 쓰며 많이 쓰이는 방법이 고정 소숫점(Fixed point) 연산이다. 연산 할 때에도, 그 값을 UART로 출력할 때에도 많이 사용한다.


myAccel-3 모듈 같은 경우에는 25MHz 클럭으로 1KHz의 내부 컨트롤 루프를 돌리며 매 루프마다 IIR 필터 3개를 돌린다. 실수 연산을 사용한다면 도저히 구현 불가능한 연산이지만, fixed point 연산을 통해 아주 여유롭게 돌아가는 시스템을 만들 수 있었다.