Main Content

이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

parfor 루프에서 변수 문제 해결하기

parfor 루프 변수는 연속으로 증가하는 정수여야 함

parfor 루프에서 루프 변수는 연속으로 증가하는 정수여야 합니다. 따라서 다음 예제는 오류를 반환합니다.

parfor i = 0:0.2:1      % not integers
parfor j = 1:2:11       % not consecutive
parfor k = 12:-1:1      % not increasing
루프 변수를 유효한 범위로 변환하면 이 오류를 수정할 수 있습니다. 예를 들어, 정수가 아닌 예제를 다음과 같이 수정할 수 있습니다.
iValues = 0:0.2:1;
parfor idx = 1:numel(iValues)
i = iValues(idx);
...
end

parfor 루프에서 오버플로 방지하기

MATLAB®parfor 루프 변수의 오버플로 가능성을 감지하는 경우 오류를 보고합니다.

오버플로 조건예제해결책

parfor 루프 범위의 길이가 루프 변수 유형의 최댓값을 초과합니다.

length(-128:127)>maxint('int8')이므로 MATLAB은 오류를 보고합니다.

parfor idx=int8(-128:127)
    idx;
end

parfor 루프 변수에 큰 데이터형을 사용하십시오. 계산에서 원래 데이터형을 유지하려면 parfor 루프 내의 parfor 루프 변수를 변환하십시오.

parfor idx=-128:127
    int8(idx);
end

parfor 루프 범위의 초기값이 루프 변수 유형의 최솟값과 동일합니다.

0=intmin('uint32')이므로 MATLAB은 오류를 보고합니다.

parfor idx=uint32(0:1)
    idx;
end

  • 이전 해결책에서처럼 더 큰 데이터형에 더 작은 최솟값을 사용합니다.

  • 값 범위를 증가시킵니다. 예를 들면 다음과 같습니다.

    parfor idx=uint32(0:1)+1
        idx-1;
    end

parfor 루프에서 변수 분류 문제 해결하기

MATLAB에서 parfor 루프에 있는 이름을 변수로 인식하면 변수는 다음 표에 있는 여러 범주 중 하나로 분류됩니다. 변수가 고유하게 분류되고 범주 요구 사항을 충족하는지 확인합니다. 요구 사항을 위반한 parfor 루프는 오류를 반환합니다.

분류설명
루프 변수루프 인덱스
슬라이스 변수서로 다른 루프의 반복에 의해 배열의 각 조각이 계산되는 배열
Broadcast Variables내부에 값을 필요로 하지만 값이 할당되지 않은 루프 앞에 정의된 변수
Reduction Variables반복 순서에 관계없이 루프 반복을 통해 값을 누적하는 변수
Temporary Variables루프 내에 생성되며 루프 외부에서 액세스되지 않는 변수

현재 어떤 변수가 있는지 알아보려면 코드 조각을 살펴보십시오. 위 표의 모든 변수 분류는 다음 코드로 표현됩니다.

변수 분류 문제에 봉착할 경우 parfor 루프의 본문을 함수로 변환하는 어려운 방법을 사용하기 전에 다음 방법을 고려해 보십시오.

  • 중첩 for 루프를 사용하여 슬라이스 배열의 요소를 참조하는 경우 parfor 루프 내 다른 곳에서는 이 배열을 사용할 수 없습니다. 왼쪽의 코드는 A가 중첩 for 루프 내에서 나눠지고 요소 참조되기 때문에 작동하지 않습니다. 오른쪽의 코드는 v가 중첩 루프 바깥쪽에서 A에 할당되기 때문에 작동합니다. 전체 행을 계산한 다음 슬라이스 출력값에 한 번만 할당을 수행하면 됩니다.

    유효하지 않음유효함
    A = zeros(4, 10);
    parfor i = 1:4
        for j = 1:10
            A(i, j) = i + j;
        end
        disp(A(i, 1))
    end
    A = zeros(4, 10);
    parfor i = 1:4
        v = zeros(1, 10);
        for j = 1:10
            v(j) = i + j;
        end
        disp(v(1))
        A(i, :) = v;
    end

  • 왼쪽의 코드는 parfor의 변수 x를 분류할 수 없기 때문에 작동하지 않습니다. x의 각각의 다른 부분에 여러 번의 할당이 있으므로 이 변수는 분류할 수 없습니다. 따라서 parfor는 루프 반복 간에 종속성 유무를 확인할 수 없습니다. 오른쪽의 코드는 x의 값을 완전히 덮어쓰기 때문에 작동합니다. 이제 parforx가 임시 변수임을 분명히 확인할 수 있습니다.

    유효하지 않음유효함
    parfor idx = 1:10
      x(1) = 7;
      x(2) = 8;
      out(idx) = sum(x);
    end
    parfor idx = 1:10
      x = [7, 8];
      out(idx) = sum(x);
    end

  • 이 예제는 구조체형 배열의 필드를 나누는 방법을 보여줍니다. 자세한 내용은 struct를 참조하십시오. 왼쪽의 코드는 parfor의 변수 a를 분류할 수 없기 때문에 작동하지 않습니다. 이 변수는 인덱싱 형식이 슬라이스 변수에 유효하지 않으므로 분류할 수 없습니다. ax 필드가 올바르게 나눠지는 것 같지만 첫 번째 수준의 인덱싱은 슬라이스 인덱싱 연산이 아닙니다. 오른쪽의 코드는 struct의 필드를 별도의 변수 tmpx로 추출하기 때문에 작동합니다. 이제 parfor는 이 변수가 나눠졌음을, 즉 슬라이스 변수임을 제대로 확인할 수 있습니다. 일반적으로 struct의 필드 또는 객체의 속성을 parfor의 슬라이스 입력 변수나 슬라이스 출력 변수로 사용할 수 없습니다.

    유효하지 않음유효함
    a.x = [];
    parfor idx = 1:10
      a.x(idx) = 7;
    end
    tmpx = [];
    parfor idx = 1:10
      tmpx(idx) = 7;
    end
    a.x = tmpx;

parfor 루프에서 구조체형 배열

임시 구조체 만들기

parfor 루프에는 점 표기법 할당을 사용하여 구조체를 만들 수 없습니다. 왼쪽 코드에서 루프 내의 두 행은 분류 오류를 생성합니다. 오른쪽 코드에서는 우회적 해결 방법으로 struct 함수를 사용하여 루프 또는 첫 번째 필드에 구조체를 만들 수 있습니다.

유효하지 않음유효함
parfor i = 1:4
   temp.myfield1 = rand();
   temp.myfield2 = i;
end 
parfor i = 1:4
    temp = struct();
    temp.myfield1 = rand();
    temp.myfield2 = i;
end
parfor i = 1:4
    temp = struct('myfield1',rand(),'myfield2',i);
end

구조체 필드 나누기

parfor 루프에는 구조체 필드를 슬라이스 입력 또는 출력 배열로 사용할 수 없습니다. 즉, 루프 변수를 사용하여 구조체 필드의 요소를 참조할 수 없습니다. 왼쪽 코드에서 루프 내의 두 행은 인덱싱으로 인해 분류 오류를 생성합니다. 오른쪽 코드에서는 슬라이스 출력값에 대한 우회적 해결 방법으로 루프에 별도의 슬라이스 배열을 사용합니다. 그런 다음 루프가 완료된 후 구조체 필드를 할당합니다.

유효하지 않음유효함
parfor i = 1:4
    outputData.outArray1(i) = 1/i;
    outputData.outArray2(i) = i^2;
end 
parfor i = 1:4
    outArray1(i) = 1/i;
    outArray2(i) = i^2;
end
outputData = struct('outArray1',outArray1,'outArray2',outArray2); 

슬라이스 입력값에 대한 우회적 해결 방법은 구조체 필드를 루프 앞의 별도 배열에 할당하는 것입니다. 이 새 배열을 슬라이스 입력값으로 사용할 수 있습니다.

inArray1 = inputData.inArray1;
inArray2 = inputData.inArray2;
parfor i = 1:4
    temp1 = inArray1(i);
    temp2 = inArray2(i);
end

parfor 루프의 본문을 함수로 변환하기

다른 방법이 모두 실패할 경우 parfor 루프의 본문을 함수로 변환하면 parfor 루프의 변수 분류 문제를 대개 해결할 수 있습니다. 왼쪽 코드에서 코드 분석기는 변수 y의 문제에 플래그를 지정하지만 해결할 수 없습니다. 오른쪽 코드에서는 parfor 루프의 본문을 함수로 변환하여 이 문제를 해결합니다.

유효하지 않음유효함
function parfor_loop_body_bad

data = rand(5,5);
means = zeros(1,5);
parfor i = 1:5
  % Code Analyzer flags problem 
  % with variable y below  
    y.mean = mean(data(:,i));
    means(i) = y.mean;
end
disp(means);
function parfor_loop_body_good

data = rand(5,5);
means = zeros(1,5);
parfor i = 1:5
    % Call a function instead
    means(i) = computeMeans(data(:,i));
end
disp(means);

% This function now contains the body
% of the parfor-loop
function means = computeMeans(data)
y.mean = mean(data);
means = y.mean;
Starting parallel pool (parpool) using the 'local' profile ... connected to 4 workers.
    0.6786    0.5691    0.6742    0.6462    0.6307

모호하지 않은 변수 이름

MATLAB이 parfor 루프 내에서 변수로 분명하게 구별할 수 없는 이름을 사용하는 경우 MATLAB은 구문 분석 시 함수를 참조한다고 가정합니다. 그런 다음 런타임에 함수를 찾을 수 없으면 MATLAB은 오류를 생성합니다. 변수 이름 항목을 참조하십시오. 예를 들어, 다음 코드에서 f(5)f라는 배열의 5번째 요소를 의미하거나 인수가 5f라는 이름의 함수를 의미할 수 있습니다. f가 코드에서 명확하게 변수로 정의되지 않은 경우 MATLAB은 코드가 실행될 때 경로에서 함수 f를 검색합니다.

parfor i = 1:n
   ...
   a = f(5);
   ...
end

투명 parfor 루프

parfor 루프의 본문은 투명해야 하는데, 이는 변수에 대한 모든 참조가 코드 텍스트에서 "볼 수 있어야"한다는 것입니다. 투명성에 대한 자세한 내용은 parfor 루프 또는 spmd 문에서 투명성 확보하기 항목을 참조하십시오.

전역 변수 및 영속 변수

parfor 루프의 본문은 global 변수 선언이나 persistent 변수 선언을 포함할 수 없습니다.

관련 항목