Main Content

"메모리 부족" 오류 해결하기

문제

코드가 많은 양의 데이터에 대해 연산을 수행하거나 메모리를 효율적으로 사용하지 못할 경우 MATLAB®이 지나치게 큰 배열 크기에 대한 반응으로서 오류를 생성하거나 메모리 부족 문제에 봉착할 수 있습니다. MATLAB에는 너무 큰 배열을 만드는 것을 방지하는 기능이 내장되어 있습니다. 예를 들어 이 코드는 오류가 발생합니다. MATLAB이 요청된 개수의 요소를 가진 배열을 생성할 수 없기 때문입니다.

A = rand(1e9);
Requested array exceeds the maximum possible variable size.

기본적으로 MATLAB은 컴퓨터의 RAM(가상 메모리 미포함)을 최대 100%까지 사용하여 배열에 메모리를 할당할 수 있으며, 배열 크기가 이 임계값을 초과하면 MATLAB은 오류를 생성합니다. 예를 들어, 다음 코드는 최대 배열 크기 제한을 초과하는 크기의 배열을 만들려고 합니다.

B = rand(1e6);
Requested 1000000x1000000 (7450.6GB) array exceeds maximum array size preference (63.7GB). This might cause MATLAB to become
unresponsive.

MATLAB 작업 공간 기본 설정의 배열 크기 제한을 끄고 지나치게 큰 배열을 만들려고 하면 MATLAB에 메모리 부족 문제가 발생하거나, 과도한 메모리 페이징(즉, RAM과 디스크 간 메모리 페이지 이동)으로 인해 MATLAB 또는 사용자의 컴퓨터까지도 반응하지 않게 될 수 있습니다.

B = rand(1e6);
Out of memory.

가능한 해결 방법

메모리 제한 문제에 부딪치더라도 MATLAB은 사용자의 상황 및 목표에 따른 몇 가지 해결책을 제공합니다. 예를 들어, 코드가 메모리를 사용하는 방법을 개선하거나, 데이터저장소 및 tall형 배열과 같은 특화된 데이터 구조를 활용하거나, 연산 클러스터 내에서 풀링된 리소스를 활용하거나, 또는 설정 및 기본 설정을 조정할 수 있습니다.

참고

여기 제시된 해결책은 MATLAB에만 해당합니다. 시스템 전체의 메모리 성능을 최적화하려면 사용자의 컴퓨터에 물리적 메모리(RAM)를 추가하거나 운영 체제 수준에서 조정해 보십시오.

더 이상 필요 없는 변수 지우기

변수가 더 이상 필요하지 않을 때는 항상 해당 변수를 지우는 것이 좋습니다. 메모리에서 항목을 지우려면 clear 함수를 사용하십시오.

이전이후
A = rand(1e4);
disp(max(A,[],"all"))
B = rand(1e4);
A = rand(1e4);
disp(max(A,[],"all"))
clear A
B = rand(1e4);

자세한 내용은 효율적인 메모리 사용을 위한 전략 항목을 참조하십시오.

적절한 데이터 저장공간 사용하기

메모리 요구 사항은 MATLAB 데이터형에 따라 다릅니다. 사용자는 적절한 데이터형 및 저장공간을 사용하여 코드에 사용되는 메모리의 양을 줄일 수 있습니다. 이 섹션의 해결책에 대한 자세한 내용은 효율적인 메모리 사용을 위한 전략 항목을 참조하십시오.

적절한 숫자형 클래스 사용하기.  사용해야 할 숫자형 클래스는 의도하는 동작에 따라 달라집니다. MATLAB에서 double은 MATLAB의 디폴트 숫자 데이터형으로, 대부분의 계산 작업에 충분한 수준의 정밀도를 제공합니다.

  • 선형 대수와 같은 복잡한 수학 연산을 수행하려는 경우 배정밀도(double) 형식 또는 단정밀도(single) 형식의 부동소수점 숫자를 사용하십시오. single형 숫자는 double형 숫자보다 더 적은 메모리를 필요로 하지만 표현되는 정밀도도 더 낮습니다.

  • 단순 산술을 수행하는 것만으로 충분하고 원래 데이터를 정수로 표현하는 경우에는 MATLAB의 정수형 클래스를 사용하십시오.

클래스(데이터형)바이트지원되는 연산
single4대부분의 수학 연산
double8모든 수학 연산
logical1논리/조건 연산
int8, uint81산술 연산과 일부 간단한 함수
int16, uint162산술 연산과 일부 간단한 함수
int32, uint324산술 연산과 일부 간단한 함수
int64, uint648산술 연산과 일부 간단한 함수

데이터 저장 시 오버헤드 줄이기.  숫자형 배열이나 문자형 배열을 생성하면 MATLAB은 메모리 블록을 할당하고 배열 데이터를 저장합니다. MATLAB은 또한 배열의 클래스와 차원 등, 배열 데이터에 대한 정보를 헤더라는 별도의 작은 메모리 블록에 저장합니다. 간단한 숫자형 배열이나 문자형 배열은 오버헤드가 가장 적으므로 가능한 경우 항상 이러한 배열을 사용하십시오. 데이터가 너무 복잡해서 단순 배열에 저장할 수 없을 때에만 다른 데이터 구조를 사용하십시오.

구조체와 셀형 배열의 경우, MATLAB은 배열에 대해서뿐 아니라 구조체의 각 필드 또는 셀형 배열의 각 셀에 대해서도 헤더를 만듭니다. 따라서, 구조체나 셀형 배열을 저장하는 데 필요한 메모리 양은 구조체나 셀형 배열에 포함된 데이터의 크기뿐 아니라 구조체나 셀형 배열이 생성된 방식에 따라서도 달라집니다. 따라서 요소의 크기가 작으면서 요소 개수는 많은 셀형 배열이나, 필드가 많으면서 그 내용은 적은 구조체는 큰 오버헤드를 가지므로 피해야 합니다.

이전이후
% S has 15,000 fields (3 fields per array element)
for i = 1:100
    for j = 1:50
        S(i,j).R = 0;  % Each field contains a numeric scalar
        S(i,j).G = 0;
        S(i,j).B = 0;
    end
end
% S has 3 fields 
S.R = zeros(100,50);  % Each field contains a numeric array
S.G = zeros(100,50);
S.B = zeros(100,50);

가능한 경우 희소 배열 만들기.  0이 아닌 요소의 수가 적은 행렬은 희소 형식을 사용하여 저장하는 것이 좋습니다. 비희소 행렬에서 0이 아닌 요소의 수가 적은 경우 이 행렬을 희소 저장 형식으로 변환하면 일반적으로 메모리 사용량과 코드 실행 시간이 줄어듭니다. MATLAB은 희소 저장 형식을 지원하는 몇 가지 함수를 제공합니다. 예를 들어, speye 함수를 사용하여 희소 단위 행렬을 만들 수 있습니다.

이전이후
I = eye(1000);
I = speye(1000);

적절한 MATLAB 클래스를 사용하여 데이터 가져오기.  fread를 사용하여 이진 파일에서 데이터를 읽어올 때, 파일에 있는 데이터의 클래스만 지정하고 데이터가 작업 공간에 있을 때 MATLAB에서 사용하는 데이터의 클래스는 지정하지 않는 실수를 사용자들이 흔히 범하곤 합니다. 메모리에서의 데이터의 클래스를 지정하지 않으면 8비트 값을 읽어도 MATLAB은 double형을 사용합니다.

이전이후
fileID = fopen("large_file_of_uint8s.bin","r"); 
A = fread(fileID,1e3,"uint8"); 
fileID = fopen("large_file_of_uint8s.bin","r"); 
A = fread(fileID,1e3,"uint8=>uint8"); 

불필요한 데이터 복사본 방지하기

메모리 사용량 및 실행 속도를 향상시키려면 코드가 불필요한 데이터 복사본을 생성하지 않도록 하십시오. 이 섹션의 해결책에 대한 자세한 내용은 불필요한 데이터 복사본 방지하기효율적인 메모리 사용을 위한 전략 항목을 참조하십시오.

임시 배열 생성 지양하기.  필요하지 않은 경우 임시 배열을 생성하지 마십시오. 예를 들어, 0으로 구성된 배열을 임시 변수로 만들고 이를 함수에 전달하는 대신 하나의 명령을 사용하여 두 작업을 모두 수행합니다.

이전이후
A = zeros(1e6,1);
As = single(A);
As = zeros(1e6,1,"single");

메모리 사전할당하기.  대규모 데이터 세트를 사용할 때 배열의 크기를 반복해서 조정하면 프로그램에 메모리 부족 문제가 발생할 수 있습니다. 원래 위치의 사용 가능한 연속 메모리를 초과할 정도로 배열을 확장하는 경우, MATLAB은 배열의 복사본을 만들고 이 복사본을 충분한 공간을 갖는 메모리 블록으로 이동해야 합니다. 이 과정에서 메모리에 원래 배열의 복사본이 두 개 존재하게 됩니다. 이런 경우, 배열에 필요한 최대 공간을 사전할당하여 메모리 사용량과 코드 실행 시간을 개선할 수 있습니다. 자세한 내용은 사전할당(Preallocation) 항목을 참조하십시오.

이전이후
x = 0;
for k = 2:1000000
   x(k) = x(k-1) + 5;
end
x = zeros(1,1000000);
for k = 2:1000000
   x(k) = x(k-1) + 5;
end

중첩 함수를 사용하여 전달할 인수 개수 줄이기.  함수를 호출할 때, 호출된 함수가 변수의 값을 수정하는 경우 MATLAB은 일반적으로 호출자 작업 공간에 변수의 임시 복사본을 만듭니다. MATLAB은 불필요한 복사본을 만들지 않기 위해 다양한 기법을 적용하지만 입력 변수의 임시 복사본을 만들지 않는 것이 가능하지 않은 경우도 있습니다.

함수 호출에서 임시 복사본을 만들지 않는 한 가지 방법은 중첩 함수를 사용하는 것입니다. 중첩 함수는 모든 바깥쪽 함수의 작업 공간을 공유하므로, 함수 호출에서 변수의 복사본을 전달할 필요가 없습니다. 자세한 내용은 중첩 함수 항목을 참조하십시오.

필요한 양의 데이터만 불러오기

메모리 문제를 해결할 수 있는 한 가지 방법은 대규모 데이터 세트 중에서 해결하려는 문제에 필요한 만큼만 MATLAB으로 가져오는 것입니다. 데이터 세트 크기는 일반적으로 데이터베이스 등의 소스에서 가져올 때는 쿼리와 일치하는 요소를 명시적으로 검색할 수 있으므로 문제가 되지 않습니다. 반면 대용량의 일반 텍스트나 이진 파일을 불러올 때 흔히 발생하는 문제입니다.

datastore 함수를 사용하면 대규모 데이터 세트를 단계적으로 사용할 수 있습니다. 데이터저장소는 데이터 세트를 작은 부분으로 구분해 한 번에 메모리로 일부씩만 불러오려고 할 때 유용합니다.

데이터저장소를 만들려면 파일 이름 또는 유사한 형식의 파일 모음이 포함된 디렉터리의 이름을 제공하십시오. 예를 들어, 하나의 파일을 사용하는 경우 다음을 따르십시오.

ds = datastore("path/to/file.csv");
폴더에 있는 파일 모음을 사용하는 경우는 다음을 따르십시오.
ds = datastore("path/to/folder/");
또한 다음과 같이 와일드카드 문자 *를 사용하여 특정 유형의 모든 파일을 선택할 수도 있습니다.
ds = datastore("path/to/*.csv");
데이터저장소는 다양한 종류의 파일 형식(테이블 형식, 이미지, 스프레드시트 등)을 지원합니다. 자세한 내용은 Select Datastore for File Format or Application 항목을 참조하십시오.

데이터저장소 외에도 MATLAB은 파일의 일부를 불러올 수 있는 몇몇 다른 함수를 제공합니다. 다음 표에는 이러한 함수의 작업 대상이 되는 파일 형식별로 함수가 요약되어 있습니다.

파일 형식부분 불러오기
MAT 파일

matfile 함수를 사용하여 생성한 객체의 요소를 참조하여 변수의 일부를 불러옵니다. 자세한 내용은 MAT 파일에서 변수의 일부를 저장 및 불러오기 항목을 참조하십시오.

텍스트

textscan 함수를 사용하면 선택한 열과 행만 읽어 들여 대용량 텍스트 파일의 일부에 액세스할 수 있습니다. textscan을 사용하여 행 개수나 반복 형식 번호를 지정하는 경우, MATLAB은 정확히 필요한 메모리 양을 사전에 계산합니다.

이진 파일

fread와 같은 로우 레벨 이진 파일 I/O 함수를 사용하면 알려진 형식의 파일 일부에 액세스할 수 있습니다. 알 수 없는 형식의 이진 파일의 경우에는 memmapfile 함수를 사용하여 메모리 매핑을 시도해 보십시오.

이미지, 오디오, 비디오, HDF

이러한 유형의 파일에서 불러올 수 있도록 지원하는 다수의 MATLAB 함수는 읽을 데이터의 일부를 선택할 수 있게 해 줍니다. 자세한 내용은 가져오기 및 내보내기에 지원되는 파일 형식에 나열된 함수 도움말 페이지를 참조하십시오.

tall형 배열 사용하기

tall형 배열은 너무 커서 메모리에 다 담을 수 없는 데이터 세트를 사용할 수 있도록 합니다. MATLAB은 한 번에 데이터의 작은 블록 단위로 작업하며 모든 데이터 청크화 작업과 처리 작업을 백그라운드에서 자동으로 수행합니다. 다음 두 가지 기본적인 방법으로 tall형 배열을 활용할 수 있습니다.

  • 메모리에 들어가기는 하지만 계산을 수행하기에는 메모리가 부족한 큰 배열을 사용하는 경우 배열을 tall형 배열로 형변환하면 됩니다.

    t = tall(A);
    이 방법을 사용하면 메모리에 다 들어갈 수는 있지만 계산 시 메모리 사용량이 너무 많아서 데이터 복사본을 만들 수 없는 큰 배열을 사용할 수 있습니다. 예를 들어, RAM이 8GB이고 행렬이 5GB인 경우 행렬을 tall형 배열로 형변환하면 메모리 부족 현상 없이 행렬에서 계산을 수행할 수 있습니다. 이 사용 방법에 대한 예제를 보려면 tall 항목을 참조하십시오.

  • 파일 기반 데이터 또는 폴더 기반 데이터의 경우, 데이터저장소를 만든 후 이 데이터저장소 위에 tall형 배열을 만들 수 있습니다.

    ds = datastore("path/to/file.csv");
    t = tall(ds);
    이 방법을 사용하면 MATLAB에서 tall형 배열의 장점을 최대한 활용할 수 있습니다. 데이터는 행 개수의 구애를 받지 않을 수 있고 MATLAB에는 메모리 부족 문제가 발생하지 않습니다. datastore는 로컬 데이터 위치와 원격 데이터 위치를 모두 사용할 수 있기 때문에 작업하는 데이터가 데이터 분석을 위해 사용 중인 컴퓨터에 있지 않아도 됩니다. 자세한 내용은 원격 데이터로 작업하기 항목을 참조하십시오.

tall형 배열에 대해 자세히 알아보려면 메모리에 담을 수 없는 큰 데이터를 위한 tall형 배열 항목을 참조하십시오.

여러 컴퓨터의 메모리 사용하기

컴퓨터 클러스터가 있는 경우, 분산 배열을 사용하여(Parallel Computing Toolbox™가 필요함) 클러스터에 있는 모든 컴퓨터의 메모리를 결합해 계산을 수행할 수 있습니다. 데이터가 메모리에 어느 정도 맞는지에 따라 병렬 풀의 워커 간에 데이터를 파티셔닝하는 다양한 방법이 있습니다. 자세한 내용은 Distributing Arrays to Parallel Workers (Parallel Computing Toolbox) 항목을 참조하십시오.

설정 및 기본 설정 조정하기

일반적으로 메모리 성능을 개선할 수 있는 가장 효과적인 방법은 코드를 다시 작성하는 것입니다. 그러나, 코드를 변경할 수 없는 경우 다음 해결책을 통해 필요한 메모리 양을 제공할 수 있습니다.

Java Virtual Machine 없이 MATLAB을 시작하거나 Java 힙 크기 줄이기.  Java® Virtual Machine(JVM™) 소프트웨어 없이 MATLAB을 시작하거나Java 힙 크기를 줄이면 사용 가능한 작업 공간 메모리를 늘릴 수 있습니다. JVM 없이 MATLAB을 시작하려면 명령줄 옵션 -nojvm을 사용하십시오. Java 힙 크기를 줄이는 방법에 대한 자세한 내용은 Java 힙 메모리 기본 설정 항목을 참조하십시오.

-nojvm을 사용하면 데스크탑 툴과 그래픽스 등 JVM에 종속된 많은 기능을 사용하지 못하게 되는 단점이 있습니다. -nodesktop 옵션을 사용하여 MATLAB을 시작해도 절약되는 메모리의 양은 많지 않습니다.

배열 크기 제한 조정하기.  배열 크기가 최대 배열 크기 기본 설정을 초과함을 알리는 오류가 발생하는 경우 MATLAB에서 이 배열 크기 제한을 조정할 수 있습니다. 배열 크기 제한을 조정하는 방법에 대한 자세한 내용은 작업 공간 기본 설정과 변수 기본 설정 항목을 참조하십시오. 이 해결책은 만들려는 배열이 현재 최대 배열 크기 제한을 초과하지만 메모리에 담을 수 없을 정도로 크지는 않은 경우에만 유용합니다. 배열 크기 제한을 끄고 지나치게 큰 배열을 만들려고 하더라도 MATLAB에 메모리 부족 문제가 발생하거나, 과도한 메모리 페이징으로 인해 MATLAB 또는 사용자의 컴퓨터까지도 반응하지 않게 될 수 있습니다.

참고 항목

| | |

관련 항목