parfor
- Циклыparfor
- Переменные Loop являются последовательными увеличивающимися целыми числамиЦиклические переменные в 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
Цикл может переполняться, она сообщает об ошибке.
Условие переполнения | Пример | Решение |
---|---|---|
Длина | Здесь MATLAB сообщает об ошибке из-за parfor idx=int8(-128:127) idx; end | Используйте больший тип данных для parfor idx=-128:127 int8(idx); end |
Начальное значение | Здесь MATLAB сообщает об ошибке из-за parfor idx=uint32(0:1) idx; end |
|
parfor
- ЦиклыКогда MATLAB распознает имя в parfor
-цикл как переменная, переменная классифицируется в одной из нескольких категорий, показанных в следующей таблице. Убедитесь, что переменные уникально классифицированы и соответствуют требованиям категории. parfor
-циклы, которые нарушают требование, возвращают ошибку.
Классификация | Описание |
---|---|
Переменные цикла | Индексы цикла |
Нарезанные переменные | Массивы, сегменты которых управляются различными итерациями цикла |
Широковещательные переменные | Переменные, заданные перед циклом, значение которых требуется внутри цикла, но никогда не назначены внутри цикла |
Переменные сокращения | Переменные, которые накапливают значение через итерации цикла, независимо от порядка итерации |
Временные переменные | Переменные, созданные внутри цикла и не доступные вне цикла |
Чтобы узнать, какие переменные у вас есть, исследуйте фрагмент кода. Все классификации переменных в таблице представлены в этом коде:
Если вы сталкиваетесь с переменными задачами классификации, рассмотрим эти подходы, прежде чем прибегнуть к более сложному методу преобразования тела 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 |
Код слева не работает, потому что переменная x
в parfor
не может быть классифицирован. Эта переменная не может быть классифицирована, так как существует несколько назначений различным частям 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
для получения дополнительной информации. Код слева не работает, потому что переменная a
в parfor
не может быть классифицирован. Эта переменная не может быть классифицирована, так как форма индексации недопустима для разрезанной переменной. Первый уровень индексации не является операцией индексации с нарезкой, хотя поле x
из a
выглядит правильно срезанным. Код справа работает, потому что вы извлекаете поле struct
в отдельную переменную tmpx
. parfor
Теперь можно правильно определить, что эта переменная срезана. В целом, вы не можете использовать поля struct
s или свойства объектов как срезанные входные или выходные переменные в 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
-цикл с использованием назначения записи через точку. В коде слева обе строки в цикле генерируют ошибку классификации. В коде справа в качестве обходного пути можно использовать 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 'local' profile ... connected to 4 workers. 0.6786 0.5691 0.6742 0.6462 0.6307 |
Если вы используете имя, которое MATLAB не может однозначно отличить как переменную внутри parfor
-цикл, во время анализа MATLAB предполагает, что вы ссылаетесь на функцию. Затем во время выполнения, если функцию не удается найти, MATLAB генерирует ошибку. См. «Имена переменных». Для примера в следующем коде f(5)
может ссылаться либо на пятый элемент массива с именем f
, или функции с именем f
с аргументом 5
. Если f
не определен четко как переменная в коде, MATLAB ищет функцию f
на пути, когда код запускается.
parfor i = 1:n ... a = f(5); ... end
parfor
- циклыТело a parfor
-цикл должен быть прозрачным: все ссылки на переменные должны быть «видны» в тексте кода. Дополнительные сведения о прозрачности см. в разделе Обеспечение прозрачности в циклах parfor или операторах spmd.
Тело parfor
-цикл не может содержать global
или persistent
объявления переменных.