본문 바로가기
Engineering

[cRIO] 4. LabVIEW Real-Time Application - 세번째

by 투썬 아빠 2013. 2. 28.



지난 포스팅에서는 Real-Time Application을 개발할 때 적합한 데이터 통신 모델에 대해 알아보았습니다. 이번 포스팅에서는 Real-Time Application을 개발할 때 메모리 관리를 어떻게 해야 하는지 알아보겠습니다.

 

이 내용들은 NI에서 제공하는 'NI LabVIEW for CompactRIO Developer's Guide'를 바탕으로 작성하였음을 미리 알려드립니다.

 

임베디드 하드웨어는 일반 데스크 탑 PC에 비하여 제한적인 CPU나 메모리 등의 리소스에 있어서 제한적인 성능을 가지고 있습니다. 이처럼 제한적인 리소스를 잘 활용하기 위해서는 적절한 소프트웨어 프로그래밍이 필요합니다. cRIO를 사용함에 있어서 비휘발성 메모리 공간인 디스크 공간과 RAM 그리고 CPU를 관리하기 위해서 어떤 사항을 고려해야 하는지 알아보도록 하겠습니다.

 

<그림 1 임베디드 어플리케이션에서느 디스크 공간, RAM, CPU등의 사용이 제한된다.>

 

 

1. Working with Limited Disk Space

만약 cRIO로 데이터 수집을 하는 어플리케이션에서 수집 된 데이터를 cRIO에 로깅 할 경우 cRIO의 비휘발성 메모리 공간을 확인하여야 합니다. cRIO의 디스크 공간은 로깅되는 파일 이외에서 어플리케이션에서 사용되는 파일, 그리고 설치된 드라이버에 영향을 받습니다. Measurement & Automation Explorer(MAX)에서 디스크의 여유공간을 확인할 수 있습니다. cRIO를 Host와 동일한 네트워크에 연결하고 MAX를 실행 시킨 다음 원격 시스템 에서 cRIO를 선택하면 '시스템 설정'에서 비어있는 디스크 공간과 메모리 공간을 확인할 수 있습니다.

 

<그림 2 MAX 상에서 cRIO의 디스크 및 메모리 공간 확인>

 

MAX에서 뿐만 아니라 프로그램적으로 디스크 공간을 확인하는 방법도 있습니다. 함수 팔레트 >> 파일 I/O >> 고급 파일 기능 >> 볼륨정보 얻기 함수를 이용하여 확인이 가능합니다.

 

<그림 3 프로그램적으로 디스크 공간 확인>

 

 

2. Working with Limited RAM

cRIO의 RAM 용량은 데스크 탑 PC보다 적습니다. 때문에 메모리 관리가 매우 중요합니다. cRIO어플리케이션을 개발하기 위해서는 두 가지 메모리 할당 방법(정적 메모리 할당, 동적 메모리 할당)에 대해 알아야 합니다. LabVIEW는 C언어와 같은 텍스트언어와 달리 메모리 할당하는 코드가 없습니다. 때문에 어떤 경우에 정적 메모리 할당이고, 동적 메모리 할당이 되는지 잘 파악하고 있어야 합니다.

 

1) 정적 메모리 할당

정적 메모리는 VI의 메모리 사용량이나 실행 중에 사용되는 고정된 크기의 데이터 등을 의미합니다. 만약 정적으로 메모리를 과다하게 할당하고자 한다면 어플리케이션이 배포되는 과정에서 에러를 발생하면서 VI 가 종료 될 것입니다. 고정된 크기의 메모리 할당은 최초에 한 번만 이루어 집니다. 이러한 종류의 메모리 할 당은 메모리 매니저가 처음 한번 만 호출이 되기 때문에 프로그램 동작의 다른 영역에 영향을 미치지 않습니다. 일반적으로 고정된 크기의 메모리 할당은 아래 그림처럼 충분한 공간 확보 >> 데이터 삽입 >> 실제 입력된 데이터만 추출로 진행이 됩니다.

 

<그림 4 충분한 여유공간을 미리 확보하고 데이터 사용>

 

2) 동적 메모리 할당

동적 메모리 할당이란 프로그램 실행 중에 메모리가 할당 되는 것을 말합니다. 동적 메모리 할당은 '메모리 매니저'가 동작하기 때문에 어플리케이션의 성능이나 정시성에 영향을 미칠 수 있습니다. 즉, Real-Time 어플리케이션의 신뢰성에 영향을 미칠 수 있는 것입니다. 만약 메모리 매니저가 동적으로 메모리를 할당하고자 하는데 연속적인 메모리 공간이 없을 경우 어플리케이션이 정지될 수 있습니다. 이처럼 Real-Time 어플리케이션을 개발 할 때는 메모리 사용에 많은 신경을 써야 합니다. 아래 사항들을 고려 하시기 바랍니다.

 

i) Avoid memory leaks by closing references

할당된 메모리는 적재적소에 해제 해주어야 합니다. 사용이 완료되고 다시 사용할 필요 없는 메모리가 계속 남아있게 될 경우 메모리 누수가 발생할 수 있습니다. 이런 경우에 지속적으로 메모리 손실이 일어나고 시스템에 무리가 갈 수 있습니다. 아래와 같은 경우에 메모리 누수가 발생할 수 있습니다. '파일 핸들', 'VI Server 참조', '드라이버 핸들', '공유변수 API 참조', 'TCP/IP ID'등과 같은 참조 및 핸들을 해제하지 않으면 메모리 누수가 발생할 수 있습니다. 참조를 초기화 하고 적절히 해제하는 것만으로도 메모리 누수를 막을 수 있습니다. 그리고 루프 내에서 일반 터미널이 아닌 시프트 레지스터를 사용하여야 메모리 관리에 보다 효율적입니다.

 

ii) Avoid overallocation by using fixed-size data

가능하다면 고정된 크기의 데이터를 사용하여 동적인 메모리 할당이 되지 않도록 하는 것이 좋습니다. 사용하는 데이터의 크기는 일정한데 가변적인 크기의 데이터 타입을 사용하거나 옵션으로 크기를 고정시키지 않는 경우가 많습니다. 아래와 같은 경우가 동적 메모리 할당이 되는 대표적인 사례입니다.

 

    - 크기가 지정되지 않은 큐

    - 가변적인 크기의 배열

    - 가변적인 크기의 문자열

    - 베리언트

 

큐는 크기를 고정시킬 수 있음에도 불구하고 많은 사용자들이 가변적인 크기를 가지도록 설정하고(기본 설정이 가변적임) 사용합니다. 그리고 문자열은 크기를 고정할 수 없기 때문에 가능하다면 enum 데이터 타입으로 대체함을 추천합니다. Real-Time 환경에서는 메모리 관리에 신경을 많이 쏟아야 하기 때문에 큐보다는 RT FIFO의 사용을 권하고 있습니다.

 

iii) Keep your contiguous memory healthy

동적으로 메모리를 할당하고 해제하면 사용되는 메모리의 연속성이 깨질 수 있습니다. 아래 그림을 보도록 하겠습니다.

 

<그림 5 메모리의 연속성이 깨지는 경우>

 

그림 5의 메모리는 총 100의 크기를 가지고 있습니다. 동적 메모리 할당 및 해제를 통해서 현재 총 40의 메모리를 사용하고 있고 60의 메모리 공간이 남아있습니다. 하지만 메모리의 연속성에 문제가 있습니다. 위의 메모리 구조에서 적용 가능한 메모리 크기는 10, 20, 30입니다. 때문에 총 60의 메모리 공간이 남아있음에도 불구하고 40의 크기를 가지는 데이터를 메모리에 할당하려고 시도하면 메모리가 부족하다는 문제가 발생합니다. 60의 메모리 공간이 남아 있지만 연속적으로 40의 크기를 할당할 메모리 공간이 없기 때문입니다. 동적 메모리 할당은 이처럼 예상하지 못한 문제를 발생할 수 있기 때문에 사용을 자제하거나 유의해야 합니다.

 

    

3. Working with Limited CPU Resources

Real-Time 어플리케이션을 개발할 때 메모리 사용만큼이나 고려해야 할 것이 바로 CPU 사용량입니다. CPU 사용량은 70% 이하로 유지하는 것이 좋습니다. 이를 넘어설 경우 정시성에 영향을 미칠 수 있기 때문입니다. 사용되고 있는 CPU 리소스는 NI 배포된 시스템 관리자에서 가능하며 RT Get CPU Loads VI를 이용하면 프로그램적으로 확인이 가능합니다.

 

<그림 6 RT Get CPU Loads VI>

 

CPU 사용량을 줄이기 위해서는 아래 사항을 고려하시기 바랍니다.

1) Timed 구조 사용 주의

Timed Loop는 정시성이 보장되기 때문에 Real-Time 어플리케이션 개발에 매우 중요한 역할을 한다고 알려드렸습니다. 하지만 While 루프에 비하여 많은 기능이 내제되어 있기 때문에 과다하게 사용할 경우 오버헤드가 발생할 수 있습니다. 때문에 꼭 필요한 경우에만 Timed 구조를 사용하시기 바랍니다.

 

2) 필요한 속도로만 Loop 실행

아무리 RTOS라 하여도 어플리케이션 동작 속도를 빠르게 하면 지터가 발생할 수 있고 CPU 사용량이 증가할 수 있습니다. 적절한 속도를 안배하여 지터와 CPU 사용량을 줄이시기 바랍니다.

 

3) 지나치게 많은 네트워크 공유변수 사용 피하기

네트워크 공유 변수를 Host PC에서 생성하여 사용할 경우 RT FIFO를 활성화하여도 정시성이 보장될 수 없습니다. 때문에 정시성을 위해 RT FIFO를 활성화 한다면 반드시 Real-Time 타겟에서 생성하시기 바랍니다. 그리고 과다한 네트워크 공유변수 사용은 CPU 사용량을 증가시키기 때문에 이 또한 주의하여야 합니다.

 

4) 태스크 분리

cRIO는 만능이 아닙니다. 적절한 어플리케이션의 구성을 하였을 때 최고의 성능을 나타냅니다. 즉 Real-Time CPU에서 모든 연산을 처리하도록 하지 말고 FPGA와 Host에도 작업을 분리하는 것이 효율적이고 정시성 보장의 지름길입니다.

 

 

지금까지 cRIO의 리소스 관리에 대해 알아보았습니다. 다음 포스팅에서는 임베디드 환경에서의 네트워크 통신에 대해 알아보겠습니다.


댓글