Main Content

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

함수에 값 전달하기

입력 인수와 함께 함수를 호출할 경우 MATLAB®은 호출하는 함수의 작업 공간에서 호출되는 함수의 파라미터 변수로 값을 복사합니다. 하지만 MATLAB은 필요하지 않은 경우 이러한 값의 복사본을 생성하지 않도록 여러 기법을 적용합니다.

MATLAB은, C++ 같은 언어와 달리, 값에 대한 참조를 정의하는 방법을 제공하지 않습니다. 대신 MATLAB은 출력값과 입력 파라미터를 여러 개 사용하도록 허용하기 때문에 어떤 값이 함수에 입력으로 들어가고 어떤 값이 함수에서 출력으로 나오는지 알 수 있습니다.

쓰기 시 복사(copy-on-write)

함수가 입력 인수를 수정하지 않는 경우 MATLAB은 입력 변수에 포함된 값의 복사본을 생성하지 않습니다.

예를 들어, 큰 배열을 함수에 전달한다고 가정하겠습니다.

A = rand(1e7,1);
B = f1(A);

함수 f1은 입력 배열 X에 포함된 각 요소에 1.1을 곱한 후 그 결과를 변수 Y에 할당합니다.

function Y = f1(X)
Y = X.*1.1; % X is a shared copy of A
end

함수가 입력값을 수정하지 않기 때문에 지역 변수 X와 호출자 작업 공간에 있는 변수 A가 데이터를 공유합니다. f1이 실행된 후, A에 할당된 값은 변경되지 않습니다. 호출자 작업 공간의 변수 B는 요소별 곱셈의 결과를 포함합니다. 입력값이 값으로 전달됩니다. 그러나 f1을 호출할 때 복사본이 생성되지 않습니다.

함수 f2는 입력 변수의 로컬 복사본을 수정하므로 로컬 복사본이 입력값 A와 공유되지 않습니다. 함수에서 X의 값이 이제 호출자 작업 공간에서는 입력 변수 A의 독립적인 복사본이 됩니다. f2가 호출자 작업 공간에 결과를 반환하면 지역 변수 X가 제거됩니다.

A = rand(1e7,1);
B = f2(A);
function Y = f2(X)
X = X.*1.1; % X is an independent copy of A
Y = X;      % Y is a shared copy of X
end

입력값을 MATLAB 표현식으로 전달하기

함수에서 반환된 값을 다른 함수에 대한 입력 인수로 사용할 수 있습니다. 예를 들어, rand 함수를 사용하여 함수 f2의 입력값을 직접 생성할 수 있습니다.

B = f2(rand(1e7,1));

rand에서 반환된 값을 유지하는 변수만 함수 f2의 작업 공간에서 임시 변수 X가 됩니다. 호출자 작업 공간에는 공유되는 값이나 값에 대한 독립적인 복사본이 없습니다. 함수 출력값을 직접 전달하면 호출되는 함수의 입력값에 대한 복사본을 생성하는 데 필요한 시간과 메모리가 절약됩니다. 이 방법은 입력값이 다시 사용되지 않는 경우에 적합합니다.

같은 위치에(In-place) 할당하기

최초 입력값을 유지할 필요가 없는 경우 그 입력값의 원래 변수에 함수의 출력값을 할당할 수 있습니다.

A = f2(A);

같은 위치에 할당하는 경우 앞서 설명한 쓰기 시 복사(copy-on-write) 동작을 따릅니다. 입력 변수 값을 수정하면 해당 값의 임시 복사본이 생성됩니다.

특정 조건에서는 MATLAB이 메모리 최적화를 적용할 수 있습니다. 다음 예제를 살펴보겠습니다. canBeOptimized 함수는 변수 A에 난수로 구성된 큰 배열을 생성합니다. 그런 다음, 로컬 함수 fLocal을 호출하여 A를 입력값으로 전달하고 로컬 함수의 출력값을 동일한 변수 이름에 할당합니다.

function canBeOptimized
A = rand(1e7,1);
A = fLocal(A);
end
function X = fLocal(X)
X = X.*1.1;
end

로컬 함수에 대한 호출 A = fLocal(A)가 출력값을 변수 A에 할당하기 때문에 MATLAB은 함수가 실행되는 동안 A의 원래 값을 유지할 필요가 없습니다. fLocal 내에서 X에 수정이 생기더라도 데이터 복사본이 생성되지 않습니다. 대입식 X = X.*1.1은 같은 위치에서 X를 수정하며 곱셈의 결과를 받을 배열을 새로 할당하지 않습니다. 로컬 함수에서 복사본을 제거하면 메모리가 절약되고 큰 배열의 실행 속도가 향상됩니다.

하지만 MATLAB은 로컬 함수에서 일어나는 할당에 배열 인덱싱이 필요한 경우 이 최적화를 적용할 수 없습니다. 예를 들어, updateCells에서 생성된 셀형 배열을 수정하려면 로컬 함수 gLocal에서 X로 인덱싱해야 합니다. 매 루프 반복 i에 대해 X{i} = X{i}*1.1 형식의 루프로 구성된 할당은 X{i}*1.1의 값을 평가하고 저장하기 위해 X{i}와 크기가 동일한 임시 변수를 생성합니다. MATLAB은 X{i}에 값을 할당한 후 임시 변수를 제거합니다.

function updateCells
C = num2cell(rand(1e7,1));
C = gLocal(C);
end
function X = gLocal(X)
for i = 1:length(X)
    X{i} = X{i}*1.1;
end
end

여러 제한 사항이 추가로 적용됩니다. 함수가 오류를 발생시킨 후에 해당 변수가 사용될 가능성이 있으면 MATLAB은 메모리 최적화를 적용할 수 없습니다. 따라서, 이러한 최적화는 스크립트, 명령줄, eval에 대한 호출 또는 try/catch 블록 내 코드에 적용되지 않습니다. 또한, MATLAB은 호출된 함수를 실행하는 도중 원래 변수에 직접 액세스가 가능한 경우에도 메모리 최적화를 적용하지 않습니다. 예를 들어, fLocal이 중첩 함수이면 부모 함수와 변수를 공유할 수 있으므로 MATLAB이 최적화를 적용할 수 없습니다. 마지막으로, MATLAB은 할당된 변수가 전역(Global) 변수이거나 영속(Persistent) 변수로 선언된 경우 메모리 최적화를 적용하지 않습니다.

같은 위치 할당을 사용하는 코드 디버그하기

MATLAB이 대입문에 인 플레이스 최적화(In-place Optimization)를 적용할 때, 대입문의 좌변에 있는 변수는 임시 상태로 설정되어 MATLAB이 대입문의 우변을 실행하기 전에 액세스할 수 없습니다. 대입문 우변의 실행 결과가 변수에 할당되기 전에 MATLAB이 디버거에서 멈춰 있는 경우, 좌변 변수를 검토하면 변수를 사용할 수 없음을 나타내는 오류가 발생할 수 있습니다.

예를 들어, 이 함수에는 변수 AB의 차원에 불일치가 있습니다.

function A  = inPlace
A = rand(100);
B = rand(99);
dbstop if error
A = A.*B;
end

함수를 실행하면 오류가 발생하고 디버거에서 실행이 멈춥니다.

inPlace
Matrix dimensions must agree.

Error in inPlace (line 5)
A = A.*B;
 
5   A = A.*B;

디버그 모드에 있는 동안 변수 A의 값을 확인하려고 하면 변수를 일시적으로 사용할 수 없기 때문에 오류가 발생합니다.

K>> A
Variable "A" is inaccessible. When a variable appears on both sides of
an assignment statement, the variable may become temporarily
unavailable during processing.

디버그할 때 유연성을 향상시키려면 코드를 리팩터링하여 같은 위치 할당을 제거하십시오. 예를 들어, 결과를 다른 변수에 할당해 보겠습니다.

function A  = inPlace
A = rand(100);
B = rand(99);
dbstop if error
% Assign result to C instead of A
C = A.*B;
A = C;
end

그러면 디버거에 있는 동안 변수 A를 볼 수 있습니다.

값 방식 전달(pass-by-value) 의미 체계를 사용하는 이유

함수로 인수를 전달하고 함수에서 값을 반환할 때 MATLAB은 값 방식 전달 의미 체계를 사용합니다. 어떤 경우에는 값 방식 전달을 사용하면 호출된 함수에서 원래 값의 복사본에 생성됩니다. 그러나 값 방식 전달 의미 체계는 몇 가지 이점이 있습니다.

함수를 호출할 때 호출자 작업 공간에서 입력 변수가 수정되지 않는다는 것을 알 수 있습니다. 따라서, 단지 값이 수정될 가능성에 대비하기 위해 함수 내에서 또는 호출하는 위치에서 입력값의 복사본을 생성할 필요가 없습니다. 반환된 값에 할당된 변수만 수정됩니다.

또한, 참조 방식으로 변수가 전달된 함수 내에서 오류가 발생할 경우 작업 공간 변수가 손상될 가능성을 없앨 수 있습니다.

핸들 객체

핸들이라고 하는 특수한 종류의 객체가 있습니다. 동일한 핸들의 복사본을 유지하는 모든 변수는 동일한 기본 객체를 액세스하고 수정할 수 있습니다. 핸들 객체는 객체가 숫자 또는 행렬과 같은 수학 객체가 아닌 창, 플롯, 장치 또는 사람과 같은 실제 객체를 나타내는 특수한 경우에 유용합니다.

핸들 객체는 이벤트 및 리스너, 소멸자 메서드, 동적 속성 지원과 같은 기능을 제공하는 handle 클래스에서 파생됩니다.

값과 핸들에 대한 자세한 내용은 핸들 클래스와 값 클래스 비교 항목과 Which Kind of Class to Use 항목을 참조하십시오.

참고 항목

관련 항목