Поиск и устранение проблем с переменными в 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Цикл может переполняться, она сообщает об ошибке.

Условие переполненияПримерРешение

Длина parfor-loop области значений превышает максимальное значение типа переменной цикла.

Здесь MATLAB сообщает об ошибке из-за length(-128:127)>maxint('int8'):

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

Используйте больший тип данных для parfor-цикл переменная. Если необходимо сохранить исходный тип данных в вычислениях, преобразуйте parfor-цикл переменная внутри parfor цикл.

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

Начальное значение parfor-loop области значений равен минимальному значению типа переменной цикла.

Здесь MATLAB сообщает об ошибке из-за 0=intmin('uint32'):

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

  • Используйте больший тип данных с более низким минимальным значением, как в предыдущем решении.

  • Увеличьте область значений значений. Для примера:

    parfor idx=uint32(0:1)+1
        idx-1;
    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 Теперь можно правильно определить, что эта переменная срезана. В целом, вы не можете использовать поля structs или свойства объектов как срезанные входные или выходные переменные в 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 '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 объявления переменных.

Похожие темы