Построение MATLAB в парфор-цикле - PullRequest
0 голосов
/ 14 января 2019

Мне нужно построить фигуры с субплотами внутри parfor -циклов, аналогично этому вопросу (что больше касается качества графиков).

Мой код выглядит примерно так:

parfor idx=1:numel(A)
    N = A(idx);
    fig = figure();
    ax = subplot(3,1,1);
    plot(ax, ...);
    ...
    saveas(fig,"..."),'fig');
    saveas(fig,"...",'png');
end

Это дает странную ошибку:

Данные должны быть числовыми, датой-временем, продолжительностью или массивом, который можно преобразовать в удвоение.

Я уверен, что проблема не в нецифровых данных, поскольку тот же код без распараллеливания работает.
В этот момент я ожидал ошибку, потому что потоки будут одновременно создавать и получать доступ к объектам фигур и осей, и я не думаю, что гарантируется, что маркеры всегда соответствуют нужному объекту (так сказать, потоки являются "перекрестными чертами").

Если я предварительно инициализирую объекты, а затем получаю к ним доступ,

ax = cell(1,numel(A)); % or ax = zeros(1,numel(A)); 
ax(idx) = subplot(3,1,1);

Я получаю еще более странные ошибки где-то в фит-вызовах, которые я использую:

Error using curvefit.ensureLogical>iConvertSubscriptIndexToLogical (line 26)
    Excluded indices must be nonnegative integers that reference the fit's input data points
Error in curvefit.ensureLogical (line 18)
    exclude = iConvertSubscriptIndexToLogical(exclude, nPoints);
Error in cfit/plot (line 46)
    outliers = curvefit.ensureLogical( outliers, numel( ydata ) );

У меня такое чувство, что оно должно работать с каким-то срезом переменных, описанным в документации , я просто не могу понять, как.

1 Ответ

0 голосов
/ 16 января 2019

Мне удалось сузить проблемы до нужной мне программы.

TLDR: не используйте фитобъекты (cfit или sfit) для участков в parfor -цикле!

Решения:

  1. Используйте оболочки типа nlinfit() или lsqcurvefit() вместо fit(). Они дают вам параметры подбора напрямую, так что вы можете вызывать их при подгонке при построении.
  2. Если вам нужно использовать fit() (по какой-то причине он единственный, который смог более или менее согласованно подгонять мои данные), извлеките параметры подгонки и затем вызовите свою функцию подбора, используя расширение ячейки.

    fitfunc = @(a,b,c,d,e,x) ( ... );
    [fitobject,gof,fitinfo] = fit(x,y,fitfunc,fitoptions(..));
    vFitparam = coeffvalues(fitobject);
    vFitparam_cell = num2cell(vFitparam);
    plot(ax,x,fitfunc(vFitparam_cell{:},x), ... );
    

Насколько я знаю, fit() требует, чтобы дескриптор функции имел последующие параметры (не вектор), поэтому, используя ячейку, вы можете избежать раздутого кода, подобного этому:

     plot(ax,x,fitfunc(vFitparam(1),vFitparam(2),vFitparam(3),vFitparam(4),vFitparam(5),x), ... );
...