Как исправить предварительно выделенную матрицу для функции parfor в Matlab?

Я хочу парализовать цикл for в Matlab. Я использую для этого функцию parfor, но получаю сообщение об ошибке из-за того, как я использовал переменную внутри цикла. кто-нибудь поможет мне исправить это. Я новичок в матлабе. Вот часть моей попытки.

Вот часть проблемной части:

CV_err=zeros(length(gamma), (Num_Tasks + 1));

parfor k=1:length(gamma)

#block of code

#
CV_err(k,1:Num_Tasks)= sum(In_Fold_Error)./size(In_Fold_Error,1);
CV_err(k,Lambda_location)= Lambda;
CV_err(k,(Num_Tasks +2))= sum(CV_err(k,1:Num_Tasks))/Num_Tasks;
end

Ошибка: цикл parfor не может быть запущен из-за того, как используется CV_err. CV_err индексируется по-разному, потенциально вызывая зависимости

Кажется, что действительные индексы ограничены в parfor .


person user51661    schedule 14.12.2015    source источник
comment
Можете ли вы опубликовать фактическое сообщение об ошибке, пожалуйста? Одна верная вещь уже заключается в том, что вы пытаетесь написать что-то в CV_err(k,(Num_Tasks +2)), хотя вы определили только его 2-е измерение как длинуNum_tasks+1   -  person BillBokeey    schedule 14.12.2015
comment
вы for loop в настоящее время парализованы   -  person GameOfThrows    schedule 14.12.2015
comment
Я знаю, но не работает.   -  person user51661    schedule 14.12.2015


Ответы (2)


Пока ваша переменная нарезана, вы обращаетесь только к k-й строке в k-й итерации, анализатор кода этого не понимает. Помогите немного матлабу, сначала поместите все данные в вектор, а потом запишите все сразу в переменную sliced.

CV_err=zeros(length(gamma), (Num_Tasks + 2));
parfor k=1:length(gamma)

%block of code

%
  temp=zeros(1,(Num_Tasks + 2));
  temp(1,1:Num_Tasks)= sum(In_Fold_Error)./size(In_Fold_Error,1);
  temp(1,Lambda_location)= Lambda;
  temp(1,(Num_Tasks +2))= sum(temp(1,1:Num_Tasks))/Num_Tasks;
  CV_err(k,:)=temp;
end

Ограничение объясняется в документации:

Форма индексации. В списке индексов для срезанной переменной один из этих индексов имеет вид i, i+k, ik, k+i или ki, где i — переменная цикла, а k — константа или простая (неиндексированная) широковещательная переменная; а любой другой индекс является скалярной константой, простой широковещательной переменной, вложенным индексом цикла for, двоеточием или концом.

Источник

person Daniel    schedule 14.12.2015

Чтобы исправить предварительное выделение, не делайте предварительное выделение. Вы просто говорите MATLAB, как он должен разделить работу между работниками; parfor это не нравится.

Ответ таков: не заставляйте циклы менять общие переменные, записывайте свои результаты отдельно, выращивайте массивы ячеек вместо матриц, т.е.

    clear CV_err;

    parfor k=1:length(gamma)
            %// here your other code
            this_CV_err                  = zeros(Num_Tasks+2,1);
            this_CV_err(1:Num_Tasks)     = sum(In_Fold_Error)./size(In_Fold_Error,1);
            this_CV_err(Lambda_location) = Lambda;
            this_CV_err(Num_Tasks+2)     = mean(this_CV_err(1:Num_Tasks));
            CV_err{k} = this_CV_err;
    end;
person Community    schedule 14.12.2015
comment
Ну, если я его заранее не выделю, то на каждой итерации он будет копипастить в разные места памяти и будет тормозить. - person user51661; 14.12.2015
comment
@ user51661 вы делаете предположения, которые не обязательно верны в многоузловых/параллельных вычислениях. Предположим, что вы выделяете память для результата на одной машине, а рабочий процесс, решающий итерацию k, находится на другой машине. Вы все еще верите, что вычисления с одной машины в памяти другой машины — это быстро? Вы действительно думаете, что запись и чтение байтов по сети быстрее, чем вычисление всего в памяти, а затем отправка только результата? - person ; 14.12.2015
comment
@CST-Link: вам необходимо предварительно выделить this_CV_err, иначе между итерациями возникнет зависимость. this_CV_err=zeros(Num_Tasks +2,1); внутри цикла parfor. - person Daniel; 14.12.2015
comment
@ Даниэль Ты прав, я исправил свой ответ. Спасибо, что заметили это. - person ; 14.12.2015