코드 품질 향상을 위해 코드를 다듬다.(II)

코드 품질 향상을 위해 코드를 다듬다.

코드 최적화(Optimization)

IAR Embedded Workbench for ARM(이하 EWARM) 제품을 이용한 코드 최적화 방안을 제시합니다. 

간략하게 최적화 과정을 살펴 보겠습니다. 컴파일러는 코드의 제어 흐름과 데이터의 변화 양상을 파악합니다. 이러한 정보를 바탕으로 동일한 결과를 가져올 수 있는 변형된 로직을 생성하게 됩니다. 만약에 소스 코드의 내용을 그대로 기계어로만 변환한다면 코드 크기에 대한 변화는 이루어지지 않을 것입니다. 또한 처리 속도에 대한 변화도 발생되지 않게 됩니다. 최적화된 코드를 생성하기 위해서는 동일한 결과를 가져오는 변형된 코드를 만들게 됩니다.

일반적으로 프로젝트 초기에는 최적화 레벨을 없음(None)으로 설정하여 사용하는 것을 권장하고 있습니다. 이는 개발자가 작성한 코드와 다르게 실행 코드가 동작하기 때문에 디버깅 작업에 어려움이 따르기 때문입니다.

 

최적화 기능이 필요한가?

요즘 MCU의 성능이 향상되고 메모리의 크기에 대한 부담도 적게 여기는 경향도 있습니다. 여러 이유로 최적화 기능을 사용하지 않은 채 진행되는 프로젝트들도 있습니다. 그러나 빠른 처리 속도 측면에서 보면 단순한 처리에 걸리는 시간뿐만이 아니라 전류 사용량하고도 관련이 됩니다. 전류 소비에 대해 매우 민감한 제품에는 이처럼 소비 전류를 감소할 수 있는 방안들은 매우 중요한 사항이 됩니다. 메모리에 대해서도 디바이스 가격은 메모리 크기와 밀접한 관계를 가지고 있으므로 실행 코드의 크기는 분명히 중요한 요소입니다. 그리고 기계어 레벨에서의 최적화 방법은 소스 코드 상에서 구현 할 수 없는 기능으로 컴파일, 링크 과정을 통해서 이루어지게 됩니다.

그렇다면 이렇게 좋은 기능을 왜 사용하지 않을까요? 최적화 기능을 사용하면 원하는 동작이 이루어지지 않는 경우 때문입니다. 이는 툴이 인식하는 내용과 개발자가 의도하는 내용이 서로 다르기 때문에 발생되는 문제입니다. 다른 시각에서 보면 소스 코드 상에서 내포하고 있는 문제점이 나타났다고 표현할 수 도 있습니다. 이러한 상호 간의 차이점을 인지하고 문제가 발생되지 않도록 조치하는 것이 중요합니다. 이를 위해서는 명확한 설정으로 애매 모호성을 배제해야 합니다. 이러한 부분들을 하나씩 구체화하여 개발자와 툴간의 인식이 분명하다면 동작 상의 문제점은 발생하지 않을 것입니다. 지금은 툴이 개발자를 이해하기를 바랄 수는 없습니다. 개발자가 툴을 이해 해야지요. ^^

 

어플리케이션 조율

어플리케이션에 대해 최적화 설정은 전체 프로젝트에 적용할 수 있습니다. EWARM에서 제공되는 최적화 기능은 4단계(레벨)로 설정이 가능하며, 최고 단계인 High의 경우 Balanced, Size, Speed의 선택이 가능합니다.  최하위인 None으로 최적화 레벨을 설정하면 코드 크기 및 속도에 있어 크기는 크고, 속도는 낮은 성능을 보여 줍니다. 만약 High 레벨에 Size를 선택하였다면 코드 크기는 작지만 속도는 speed 설정 보다  떨어지는 상태가 됩니다. 그러면 High 레벨에서 Speed로 설정한 경우는 어떤 양상을 보일까요?  예상한 것처럼 속도는 빠르지만 코드 크기는 Size로 설정한 것보다 실행 코드 크기가 크게 생성됩니다.

EWARM에서 가장 빠른 실행 코드를 생성하고 싶은 경우에는 High레벨, Speed 그리고 No Size constraints를 선택하면 됩니다. 생성되는 실행 코드의 크기는 커지지만 처리 속도는 가장 빠른 코드를 생성합니다.  최적화 레벨 사이의 상관 관계는 Y축에 크기(size)를 , X축에 속도(speed)를 놓고 그래프를 그려 보면 각 레벨 설정에 대한 실행 코드의 상태를 쉽게 파악 할 수 있습니다.

최적화 설정은 프로젝트 옵션의 C/C++ Compiler 카테고리의 Optimization 탭에서 설정할 수 있으며, 프로젝트 전체에 지정할 수 있고, 파일(그룹) 단위로도 설정이 가능합니다. 그리고 함수 단위는 #pragma optimize 지시어를 이용하여 설정할 수 있습니다.

전체 프로젝트를 High, Size로 설정하여 코드 크기를 전체적으로 작게 생성할 수 있습니다. 여기에 특정 파일들은 처리 속도에 민감한 경우라면 해당 파일들만을 High, Speed로 설정이 가능합니다. 워크스페이스 윈도우에서 해당 파일을 선택한 후  마우스 오른쪽 버튼을 클릭하고 Options를 실행합니다. 대화창이 표시되면 Override inherited setting을 선택하고 최적화 설정을 변경하면 됩니다.

또한 처리 속도 향상을 위해서는 많이 동작하는 함수를 좀 더 빠르게 설정하면 도움이 될 것입니다. 함수의 동작 빈도는 C-SPY 디버거의 Function profiler 윈도우에서 확인이 가능합니다.

동작 빈도가 높은  함수의 바로 앞에 #pragma optimize = no_size_constraints 지시어를 소스 코드에 추가하면 해당 함수에 대해 크기를 고려하지 않고 빠른 속도의 코드를 생성하게 됩니다.

앞서 살펴본 바와 같이 최적화 설정은 파일 단위뿐만이 아니라 함수 단위까지도 부분적으로 세밀하게 지정할 수 있습니다. 여러분들의 코드를 좀 더 세밀하게 설정해 주어 크기와 속도 사이의 밸런스를 찾는 다면 보다 좋은 품질의 실행 이미지가 생성될 것입니다.

감사합니다.

본 글은 IAR 시스템즈 코리아 기술팀 고성용 상무가 작성하였습니다.

© IAR Systems 1995-2017 - All rights reserved.