parfor 루프에서 변수 문제 해결하기
parfor 루프 변수가 연속된 정수인지 확인하기
parfor 루프에서 루프(반복문) 변수는 연속된 정수여야 합니다. 이러한 이유로 다음 예시들은 오류를 반환합니다.
parfor i = 0:0.2:1 % not integers parfor j = 1:2:11 % not consecutive
iValues = 0:0.2:1; parfor idx = 1:numel(iValues) i = iValues(idx); ... end
R2026a 이전: 루프 변수는 증가하는 연속된 정수여야 합니다. 이러한 이유로 다음 예시는 오류를 반환합니다.
parfor k = 12:-1:1 % not increasing
parfor 루프에서 오버플로 방지하기
MATLAB®은 parfor 루프 변수의 오버플로 가능성을 감지하는 경우 오류를 보고합니다.
| 오버플로 조건 | 예제 | 해결책 |
|---|---|---|
|
parfor idx=int8(-128:127) idx; end |
parfor idx=-128:127 int8(idx); end |
|
parfor idx=uint32(0:1) idx; end |
|
parfor 루프에서 변수 분류 문제 해결하기
MATLAB에서 parfor 루프에 있는 이름을 변수로 인식하면 변수는 다음 표에 있는 여러 범주 중 하나로 분류됩니다. 변수가 고유하게 분류되고 범주 요구 사항을 충족하는지 확인합니다. 요구 사항을 위반한 parfor 루프는 오류를 반환합니다.
| 분류 | 설명 |
|---|---|
| 루프 변수 | 루프 인덱스 |
| 슬라이스 변수 | 서로 다른 루프의 반복에 의해 배열의 각 조각이 계산되는 배열 |
| 브로드캐스트 변수 | 루프(반복문) 전에 정의되어 루프 내에서 사용되지만, 루프 내에서 값이 할당되지 않는 변수 |
| Reduction 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의 값을 완전히 덮어쓰기 때문에 작동합니다. 이제parfor는x가 임시 변수임을 분명히 확인할 수 있습니다.유효하지 않음 유효함 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를 분류할 수 없기 때문에 작동하지 않습니다. 이 변수는 인덱싱 형식이 슬라이스 변수에 유효하지 않으므로 분류할 수 없습니다.a의x필드가 올바르게 나눠지는 것 같지만 첫 번째 수준의 인덱싱은 슬라이스 인덱싱 연산이 아닙니다. 오른쪽의 코드는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); end | 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); end % This function now contains the body % of the parfor-loop function means = computeMeans(data) y.mean = mean(data); means = y.mean; end Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
0.6786 0.5691 0.6742 0.6462 0.6307 |
모호하지 않은 변수 이름
MATLAB이 parfor 루프 내에서 변수로 분명하게 구별할 수 없는 이름을 사용하는 경우 MATLAB은 구문 분석 시 함수를 참조한다고 가정합니다. 그런 다음 런타임에 함수를 찾을 수 없으면 MATLAB은 오류를 생성합니다. 변수 이름 항목을 참조하십시오. 예를 들어, 다음 코드에서 f(5)는 f라는 배열의 5번째 요소를 의미하거나 인수가 5인 f라는 이름의 함수를 의미할 수 있습니다. f가 코드에서 명확하게 변수로 정의되지 않은 경우 MATLAB은 코드가 실행될 때 경로에서 함수 f를 검색합니다.
parfor i = 1:n ... a = f(5); ... end
작업 공간에 변수가 존재하는지 확인하기
MATLAB이 구문 분석 시 함수 내 parfor 루프에 브로드캐스트 또는 슬라이스 입력 변수가 포함된다고 판단하는 경우, parfor 루프 실행 전에 해당 변수에 값을 할당해야 합니다. 이 요구사항은 parfor 루프 내의 조건부 코드로 인해 런타임에 해당 값이 필요하지 않더라도 여전히 적용됩니다.
왼쪽의 잘못된 코드에서 someCondition 변수는 항상 false이므로, 함수 작업 공간에서 MATLAB이 data 변수를 생성하지 못하고 parfor 루프에서 data 변수를 사용할 수 없습니다. 그러나 MATLAB은 여전히 data를 브로드캐스트 변수로 식별합니다. data가 런타임에 함수 작업 공간에 존재하지 않으면, MATLAB은 오류를 발생시킵니다. 오른쪽의 유효한 코드에서는 someCondition의 값과 무관하게 data 변수에 값을 할당함으로써 이 문제를 해결합니다.
| 유효하지 않음 | 유효함 |
|---|---|
function out = invalidParforCode someCondition = rand > 1; if someCondition data = rand(5,5); end parfor ii = 1:5 if someCondition out(ii) = sum(data); % data classified as broadcast variable else out(ii) = 7; end end end % Run the function out = invalidParforCode; | function out = validParforCode someCondition = rand > 1; data = rand(5,5); parfor ii = 1:5 if someCondition out(ii) = sum(data); % data classified as broadcast variable else out(ii) = 7; end end end % Run the function out = validParforCode; |
투명 parfor 루프
parfor 루프의 본문은 투명해야 하는데, 이는 변수에 대한 모든 참조가 코드 텍스트에서 “볼 수 있어야” 한다는 것입니다. 투명성에 대한 자세한 내용은 parfor 루프 또는 spmd 문에서 투명성 확보하기 항목을 참조하십시오.
전역 변수 및 영속 변수
parfor 루프의 본문은 global 변수 선언이나 persistent 변수 선언을 포함할 수 없습니다.