메모리 오버플로를 일으킨 메모리에 임시 행렬을 만들지 않고 행렬을 '복사'하는 방법은 무엇입니까?


9

더 큰 할당 된 메모리에 매트릭스를 할당하면 matlab은 어떻게 든 '복사'하는 동안이를 복제하고 복사 할 매트릭스가 충분히 큰 경우 메모리 오버 플로우가 발생합니다. 이것은 샘플 코드입니다.

main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
    parfor i=1:n
        slice_matrix(:,:,i)=gather(gpuArray(rand(500,500)));
    end
    main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end

단지 '분쇄'를 할 수있는 방법 slice_matrix을 위에 main_mat오버 헤드없이? 미리 감사드립니다.

편집하다:

main_mat사전에 할당 할 때 오버 플로우가 발생했습니다 . 경우 main_mat에 초기화된다 main_mat=zeros(500,500,1);(작은 크기), 오버 플로우가 발생하지 않겠지 만 행렬은 그것으로 할당되기 전에 할당이 수행되지 않기 때문에 감속한다. 범위가 k증가함에 따라 성능이 크게 저하됩니다 .


1
루프와 관련하여 : 최적화를 위해 외부 루프를 루프로 설정하는 것이 좋습니다parfor . 또한 parfor데이터를 각 개별 작업자에게 복사하여 4 명의 작업자가 데이터를 RAM에 4 번 복제한다고 가정합니다.
Adriaan

1
Matlab이 실제로 메모리를 복제하고 있다는 표시는 무엇입니까? memory기능 을 사용하고 있습니까? 작업 관리자? Matlab의 메모리 오류? 어떤 코드 라인에서 발생합니까?
Eliahu Aaron

내가 코드에 주석을 달 았던 곳을 볼 수 있듯이 main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)메모리 오버플로 문제가 발생합니다. main_mat미리 할당 할 때 확인되며 오버플로가 발생하지 않으면 오버플로가 발생합니다. Matlab은 '메모리 부족 오류'를 반환합니다.
Gregor Isack

500x500x2000 매트릭스가 메모리에 맞습니까? ~ 4Gb입니다. 어레이에 쓸 때만 메모리 부족 오류가 발생할 수있는 이유는 stackoverflow.com/q/51987892/7328782 를 참조하십시오 .
Cris Luengo 2014

문제를 더 잘 이해하려면 h=h+slice_matrix(end)이전을 삽입하고 main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;0으로 h를 초기화 할 수 있습니까? 새로 추가 된이 줄이 이미 메모리 문제를 일으킬 것으로 의심됩니다.
Daniel

답변:


4

주요 문제는 숫자가 0보다 많은 공간을 차지한다는 것입니다. GPU를 사용하든 parfor를 사용하든 관계없이 많은 main_mat=zeros(500,500,2000);RAM을 main_mat = rand(500,500,2000);차지하지만 실제로는 RAM을 더 많이 사용합니다. 따라서 이것은 부 자연스러운 메모리 팽창이 아닙니다. 아래의 Daniel의 링크에 따르면 0을 할당하면 메모리에 대한 포인터 만 생성되고 실제 메모리는 "숫자"에 행렬을 사용할 때만 채워집니다. 운영 체제에서 관리합니다. 그리고 Windows, Mac 및 Linux에서도 예상됩니다. Matlab 또는 C와 같은 다른 언어로 수행하십시오.


지금은 더 이상 MATLAB을 이해하지 못합니다. zeros전체 가상 메모리가 있는 명령을 입력하면 실제로 할당되지만 메모리는 사용되지 않습니다. whos는 두 매트릭스에 대해 동일한 크기를 보여 주며, os는 다른 메모리 소비를 보여줍니다. 귀하의 답변이 확실히 틀리지 않기 때문에 내 의견을 삭제했습니다.
다니엘

3
나는 이것을 설명하는 것을 발견했다 : stackoverflow.com/questions/51987892/…
Daniel

좋은 대답입니다! 감사.
JLev

@Gregor : 이것을 확인하고 ones대신 대신 사용해보십시오 zeros. 이는 각 함수를 호출 할 때 실제로 메모리가 할당되도록합니다.
다니엘

모든 것을 올바르게 이해하면 결론은 다음과 같습니다. 임시 사본이 없습니다. main_mat0이 아닌 값이 할당되어 메모리 부족 예외가 발생 합니다. 이전에는 가상 메모리 (주소 공간) 만 할당되었으므로 이제는 실제 메모리에 할당됩니다.
다니엘

1

제거 parfor하면 문제가 해결 될 수 있습니다.

parfor거기에 유용하지 않습니다. MATLAB parfor은 공유 메모리 병렬 처리를 사용하지 않고 (즉, 새 스레드를 시작하지 않음) 분산 메모리 병렬 처리 (새 프로세스를 시작 함)를 사용합니다. 세트 또는 작업자 노드에 작업을 분배하도록 설계되었습니다. 또한 하나의 노드 (또는 단일 데스크탑 컴퓨터) 내에서 작동하여 여러 코어에 작업을 분배하지만 하나의 노드 내에서 병렬 처리를 수행하는 최적의 방법은 아닙니다.

즉, 시작한 각 프로세스 parfor에는 자체 사본이 있어야합니다 slice_matrix. 이는 프로그램에서 사용하는 많은 양의 메모리의 원인입니다.

MATLAB 문서에서 " 사용시기 결정"을parfor 참조 하여 사용parfor 시기 및 사용시기에 대해 자세히 알아 보십시오.


1
제거 parfor 가 유일한 방법 입니까? 내부의 모든 parfor것이 CPU와 GPU를 많이 사용하므로 성능을 크게 향상 시켰기 때문에 처리 방식을 설계했을 때 가장 잘 작동 합니다.
Gregor Isack

@GregorIsack : 예제 코드를 사용하여 실제로 내부에서 많은 작업을 수행했는지 몰랐습니다 parfor. 그렇다면, 유용 할 것입니다. - slice_matrix아닌 경우 gpuarray할당에 복사되지 않습니다.
Cris Luengo

slice_matrix이 아닌 경우에도 gpuArray여전히 오버플로 증상이 나타납니다. 이 질문을 열어 보도록하겠습니다. 다른 해결책이 있는지 봅시다. 그래도 답변 주셔서 감사합니다!
Gregor Isack

0

귀하의 코드는 샘플 코드이며 rand()MVE의 사용자 지정 을 나타내는 것으로 가정합니다 . 따라서 matlab의 메모리 사용에 대한 힌트와 요령이 있습니다.

The MathWorks 교육 핸드북의 스 니펫이 있습니다.

MATLAB에서 매개 변수를 함수에 전달할 때 발생하는 것처럼 MATLAB에서 한 변수를 다른 변수에 할당하면 MATLAB은 해당 변수에 대한 참조를 투명하게 만듭니다. MATLAB은 코드가 하나 이상의 값을 수정하는 경우에만 참조를 끊고 해당 변수의 복사본을 만듭니다. copy-on-write 또는 lazy-copying 으로 알려진이 동작 은 코드가 값을 수정할 때까지 큰 데이터 세트를 복사하는 비용을 지연시킵니다. 따라서 코드가 수정을 수행하지 않으면 변수를 복사하기 위해 추가 메모리 공간과 실행 시간이 필요하지 않습니다.

가장 먼저 할 일은 코드의 (메모리) 효율성을 확인하는 것입니다. 뛰어난 프로그래머의 코드조차 (약간의) 두뇌 능력으로 더 최적화 될 수 있습니다. 다음은 메모리 효율성에 관한 힌트입니다.

  • MATLAB의 nativ 벡터화의 메이크업 사용, 예를 들어 sum(X,2), mean(X,2),std(X,[],2)
  • matlab이 행렬을 확장 할 필요가 없는지 확인하십시오 ( 암시 적 확장 이 최근에 변경됨). 사용하는 것이 더 효율적일 수 있습니다bsxfun
  • 사용 장소-작업, 예를 들면 x = 2*x+3보다는x = 2*x+3
  • ...

메모리 사용에 관한 최적은 계산 시간을 줄이려는 것과 같지 않습니다. 따라서 작업자 수를 줄이거 나 parfor-loop 를 사용하지 않는 것이 좋습니다. (AS는 parfor전혀 없다, 공유 메모리를 사용할 수 없습니다 복사 (copy-on-write) 병렬 도구 상자를 사용하여와 기능.

사용 가능한 메모리 와 사용 가능한 메모리 및 Matlab에서 사용할 수있는 메모리를 자세히 보려면 체크 아웃하십시오 feature('memstats'). 당신에게 흥미로운 것은 가상 메모리 입니다.

전체 MATLAB 프로세스와 관련된 총 사용 가능한 메모리. 프로세서 아키텍처 및 운영 체제에 의해 제한됩니다. 또는이 명령을 사용하십시오 [user,sys] = memory.

빠른 사이드 노드 : Matlab은 매트릭스를 메모리에 일관되게 저장합니다. 큰 행렬에는 큰 여유 RAM 블록이 필요합니다. 변수를 변경하면 Matlab이 현재 스팟을 초과 할 때마다 전체 매트릭스를 RAM의 더 큰 스팟으로 복사하기 때문에 변수를 할당하려는 이유이기도합니다.

실제로 메모리 문제 가있는 경우 저급 언어에서 요구하는 데이터 형식 기술을 파고 드는 것이 좋습니다. 예를 들어 시작부터 직접 단 정도를 사용하여 메모리 사용량을 절반으로 줄일 수 있습니다 main_mat=zeros(500,500,2000,'single');-btw, rand(...,'single')더 많은 기본 기능 과 함께 작동 하지만 더 복잡한 matlab 함수는 double 유형의 입력이 필요하지만 다시 캐스트.


0

내가 올바르게 이해하면 주요 문제는 parfor메모리를 공유 할 수 없다는 것입니다. 모든 parfor worker를 거의 별도의 matlab 인스턴스로 생각하십시오.

Fileexchange의 '공유 매트릭스'인 https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix 는 기본적으로 한 가지 해결 방법이 있습니다 (내가 시도한 적이 없음).

더 많은 솔루션 : 다른 사람들이 제안한 것처럼 : parfor 제거는 확실히 하나의 솔루션, 더 많은 램 가져 오기, 키가 큰 배열 사용 (ram이 꽉 찼을 때 하드 드라이브 사용, 여기 읽기 ), 작은 덩어리로 작업 나누기, 마지막으로, 적어도 다른 대안을 고려하십시오 MATLAB.


0

다음 코드를 사용할 수 있습니다. 실제로 slice_matrix가 필요하지 않습니다

main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
   parfor i=1:n
       main_mat(:,:,1+(k-1)*n + i - 1) = gather(gpuArray(rand(500,500)));
   end
   %% now you don't need this main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end

parfor 루프 안에서는 그렇게 할 수 없습니다
Gregor Isack

시도 했습니까?
mayank1513

내가 그것을 parfoor 루프 밖으로 옮긴 이유가 있습니다. 나는 똑같은 코드를 시도하지 않았지만 인덱싱 때문에 작동하지 않을 것이라는 것을 알았습니다.
Gregor Isack
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.