IDL/Miscellaneous

IDL에서 메모리를 절약하는 팁 (DELVAR, TEMPORARY)

이상우_IDL 2023. 3. 23. 14:28
728x90

우리가 IDL에서 많은 변수 및 배열들을 갖고 작업을 하다보면 이러한 항목들이 메모리를 점점 차지하게 됩니다. 특히 배열의 경우 크기가 클수록 한번에 차지하는 메모리의 양이 결코 적지 않습니다. 그런데 만약 이런 배열들을 여러 개를 한꺼번에 정의하여 처리하게 되면, 컴퓨터의 사양에 따라서는 작업의 속도 및 효율이 저하되는 경우가 종종 있습니다. 또한 배열 자체는 한두개 정도라 하더라도 그 용량이 크고 여러 단계의 과정들을 거처 이러한 배열 데이터를 계속 처리해가는 작업을 할 경우에도 비슷한 현상이 발생할 수 있습니다. 특히 2차원 또는 3차원 데이터를 갖고 작업하면서 이런 현상을 경험해보신 유저들도 있을 것이라 봅니다. 저도 물론 그런 경험들을 많이 했었습니다.

 

이와 같은 메모리 문제를 해결하기 위해서는 대용량의 메모리 점유 상황을 풀어주는 기법을 동원해야 합니다. 물론 IDL에서는 이렇게 메모리를 차지하고 있는 변수나 배열에 관한 기억을 지워줄 수 있는 기능들이 몇가지 있습니다. 일단 첫번째로 소개할 방법은 바로 DELVAR 명령을 사용하는 것입니다. 이 명령은 커맨드 입력창에서만 사용이 가능하며 개별 변수나 배열 등과 같이 메모리를 차지하고 있는 항목을 메모리상에서 제거하는 역할을 담당합니다. 예를 들어 커맨드 입력창에서 다음과 같이 1만개의 실수값들로 구성된 배열을 하나 선언해봅시다. 이 때, 배열을 선언하기 전과 후의 메모리 변화를 확인하기 위하여 HELP 명령/MEMORY 키워드와 함께 사용하는 것이 효과적입니다.

 

IDL> HELP, /MEMORY

IDL> a = FLTARR(10000)

IDL> HELP, /MEMORY

 

그러면 아래와 같은 내용이 출력이 됩니다. 여기서 heap memory used라는 항목에 명시된 숫자를 보면 되는데요. 사실 아래 내용은 실제로 제 컴퓨터에서 위와 같은 내용을 수행한 결과입니다. 구체적인 숫자는 각자 컴퓨터의 상황에 따라 다를 수는 있습니다. 하지만 사용중인 메모리의 용량이 증가하였음을 확인할 수 있습니다. 구체적으로는 약 40000 byte 정도가 증가해 있습니다.

 

IDL> HELP, /MEMORY
heap memory used:    6712564, max:    6712611, gets:  4272504, frees:  4266379
IDL> a = FLTARR(10000)
IDL> HELP, /MEMORY
heap memory used:    6752870, max:    6752987, gets:  4272516, frees:  4266388

 

이것은 실수(Float)라는 자료형의 값 하나는 4 byte의 메모리를 차지하기 때문입니다. 배열의 크기 또는 갯수가 더 많으면 당연히 더 많은 메모리가 점유가 됩니다. 그러면 여기서 배열 a를 메모리상에서 제거하는 방법이 무엇일까요? 바로 DELVAR 명령을 사용하는 것입니다. 그래서 다음과 같이 DELVAR 명령을 수행한 후 메모리의 변화를 확인해볼 수 있습니다.

 

IDL> delvar, a
IDL> help, /memory
heap memory used:    6712848, max:    6753117, gets:  4272544, frees:  4266415

 

보시다시피 a라는 배열은 메모리상에서 사라지고, heap memory used의 양은 거의 처음의 값 수준으로 회복되어 있음을 확인할 수 있습니다. 그래서 이 DELVAR라는 명령을 적절한 시점에서 사용하면 메모리의 절약에 상당히 도움이 됩니다. 그런데, DELVAR의 약점이 있습니다. 바로 커맨드 입력창에서만 사용이 가능할 뿐이고 프로시저(프로그램)의 내부에서는 사용이 불가능합니다. 따라서 하나의 프로시저 안에서도 변수나 배열을 중간중간에 적절하게 제거하기 위해서는 다른 방법이 필요합니다. 그 방법이 바로 두번째로 소개할 TEMPORARY 함수를 사용하는 방법입니다. 이 TEMPORARY 함수는 프로그램 내부에서 또는 커맨드 입력창에서도 모두 사용이 가능합니다. 일단 TEMPORARY 함수를 사용하면서 !null과 연동시키는 기법부터 살펴보겠습니다. 만약 a라는 대용량의 데이터 배열이 존재할 때, TEMPORARY 함수를 이용하여 a를 메모리상에서 제거하는 방법은 다음과 같습니다.

 

!null = TEMPORARY(a)

 

이렇게 하면 a라는 배열을 메모리상에서 제거하는 작업을 프로시저(프로그램) 내에서 수행할 수 있습니다. 그래서 이러한 방법의 효과를 확인하기 위하여 아래와 같은 내용의 프로그램을 만들어 보았습니다. 이 내용을 카피하여 test_memory_save.pro라는 프로시저로 저장한 다음 컴파일 및 실행을 해보세요. 그러면서 중간중간에 HELP 명령에 의하여 출력되는 내용을 보면, 배열 a로 인하여 일정량의 메모리가 점유되었다가 a가 제거되면서 메모리가 다시 원래 상태로 회복되는 것을 확인할 수 있습니다.

 

PRO test_memory_save

 

HELP, /MEMORY
a = FLTARR(10000)
HELP, /MEMORY
!null = TEMPORARY(a)
HELP, /MEMORY

 

END

 

또는 이런 경우도 있습니다. 어떤 대용량의 데이터 배열에 대하여 이런 저런 처리를 순차적으로 해가면서 그 중간중간의 부산물들이 계속 누적되는 경우인데요. 예를 들면 다음과 같은 경우입니다.

 

a = HANNING(1000, 1000)

b = a*100

c = SQRT(b)

HELP, a, b, c

 

이와 같이 초기 데이터에 해당되는 배열 a에 대하여 추가적인 연산을 수행하여 그 결과를 b, c 등으로 변환하는 경우입니다. 만약 위와 같이 처리할 경우에는 최종 단계에서도 a, b, c가 모두 메모리상에 존재하게 됩니다. 이것은 HELP 명령에 의하여 출력된 내용으로부터 확인할 수 있습니다.

 

A               FLOAT     = Array[1000, 1000]
B               FLOAT     = Array[1000, 1000]
C               FLOAT     = Array[1000, 1000]

 

즉 배열 a, b, c가 각자 메모리를 점유하게 됩니다. 그런데 최종 결과물인 c만 필요하고 그 이전 단계에 사용되는 a, b는 결국 필요가 없게 되는 상황을 가정해봅시다. 그렇다면 a, b는 중간과정에서만 필요할 뿐 최종적으로는 굳이 존재하지 않아도 됩니다. 이럴 경우에는 TEMPORARY 함수를 다음과 같이 활용해보는 것도 괜찮습니다.

 

a = HANNING(1000, 1000)

b = TEMPORARY(a)*100

c = SQRT(TEMPORARY(b))

HELP, a, b, c

 

이와 같이 처리를 하면 b를 얻으면서 a는 바로 메모리상에서 제거되고, c를 얻으면서 b가 메모리상에서 바로 제거되는 효과를 얻을 수 있습니다. 그러면 최종적으로는 c만 남고 a, b는 이미 제거된 상태가 됩니다. HELP에 의하여 출력된 내용을 보면 이 사실을 바로 확인할 수 있습니다.

 

A               UNDEFINED = <Undefined>
B               UNDEFINED = <Undefined>
C               FLOAT     = Array[1000, 1000]

 

이렇게 하면 a, b가 차지했던 메모리가 중간에 이미 제거된 상태가 되기 때문에 결국 최종 결과물인 c만 메모리를 점유하게 됩니다. 이와 같이 TEMPORARY 함수를 적절히 활용한다면 전체적인 프로그램 처리과정에서 불필요하게 과도한 메모리가 점유되는 현상을 어느 정도 완화시킬 수 있게 됩니다. 만약 a. b, c 등이 용량이 엄청 큰 데이터 배열일 경우라면 메모리의 적절한 관리 여부는 결국 전체적인 과정이 원활하게 실행되느냐 아니면 중간에 메모리 이슈로 인하여 프로그램이 뻗어버리느냐를 좌우할 수도 있습니다.

 

어쨌든 우리가 방대한 양의 데이터를 처리하는 프로그램을 작성하고 실행할 경우에는 자칫 메모리의 양이 부족해지는 상황이 발생할 수 있으며, 그럴 경우에는 프로그램 내에서 쓸데없이 점유된 메모리를 적절한 시점에 풀어주는 것이 반드시 필요할 수도 있게 됩니다. 그럴 경우에 오늘 소개한 방법들을 적절히 활용하면 대용량의 데이터를 처리하는 작업에 있어서 메모리를 절약하면서 작업이 원활하게 수행될 수 있도록 할 수 있다는 것을 참조하시면 좋을 것 같습니다. 오늘 소개된 내용은 원래 2014년 5월 15일에 IDL Datapoint라는 블로그에 올라왔던 게시물의 내용 일부를 참조하였음을 밝혀둡니다.

 

* 앞서 언급한 원문의 링크는 원래 여기였지만 아쉽게도 지금은 링크가 사라져서 볼 수가 없습니다.

* 이 게시물은 제가 원래 2014년 5월 28일에 올렸던 내용을 수정 및 보완하여 2023년에 다시 올리는 게시물입니다.

LIST