0

So I am trying to call this function using a parfor (basically curve fitting using Fourier series through a vector in a parfor loop):

function[coefnames,coef] = fourier_regression(vect_waves,n)

    coef = zeros(length(vect_waves)-n,18);
    current_coef = zeros(18,1); % All the terms of the fourier series
    x = 1:n;

    parpool_obj = parpool;
    parfor i=n:length(vect_waves)

        take_fourier = vect_waves(i-n+1:i);

        f = fit(x,take_fourier,'fourier8');
        current_coef = coeffvalues(f);
        coef(i,1:length(current_coef)) = current_coef;

    end
    coefnames = coeffnames(f);

    delete(parpool_obj);
end

But I am just getting the error

"The variable coef in a parfor cannot be classified. See Parallel for Loops in MATLAB, "Overview".

I can't seem to find the solution anywhere, I don't know what the problem is. What's going on?

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Luis Cruz
  • 1,488
  • 3
  • 22
  • 50

2 Answers2

1

You are trying to fill an array before the amount of elements to be filled is known. What that means is that your loop has a different length of current_coef, which cannot be determined before the loop is run. You need to define everything before the parallel loop executes, because the order of execution is not predetermined.

The way to solve this is given by @AndrasDeak in the comments on this post. (I did not know the function, or that it always output the same number of elements, hence I could only give an explanation as to why this code does not work, but not the solution)

In general it is best to first optimise your code in terms of speed, then try and go parallel. Even without regression. Parallel processing is not some magic want you wave over sloppy code to magically make it execute faster, it is a highly optimised tool which works best on optimised codes.

For a better overview of parfor see Saving time and memory using parfor in Matlab?

Note you called this piece of code a "regression" in one of your earlier posts today, which it is not. If it were regression, however, parfor would not work.

Community
  • 1
  • 1
Adriaan
  • 17,741
  • 7
  • 42
  • 75
  • Is there anything I can do for this type of regression then? What would you recommend? CUDA? or am I better off if I write my own fourier series code? – Luis Cruz Oct 27 '15 at 11:57
  • The problem with regression is that you need a sequential loop, which is impossible using `parfor`, check the documentation on that + the linked answer. Since I am not very familiar with regression algorithms I cannot help you on that alas. – Adriaan Oct 27 '15 at 11:58
  • @LuisCruz, the number of coefficients in a `fourier8` fit is know *a priori*, isn't that right (and 18)? In this case you can actually set the length of `current_coef` by hand, before the loop, and using `coef(i,:)=...` on the problematic assignment (after initializing `coef` to the proper dimensions). If I'm right, the only problem is that the interpreter can't know for sure that all those vectors are the same size, but you can fix this by being explicit. – Andras Deak -- Слава Україні Oct 27 '15 at 12:19
  • YES! That's correct. I even tried preallocating that with the known 18 fourier series values (see updated code), but I was still getting the same error message.... – Luis Cruz Oct 27 '15 at 12:34
  • @AndrasDeak you are quite right, I took the liberty of putting this comment as an answer. – Edric Oct 27 '15 at 13:16
  • @Adriaan I see nothing order-dependent in the loop - the problem really does appear to be as simple as keeping the `parfor` variable indexing happy, which is simple in this case. – Edric Oct 27 '15 at 13:17
  • @Edric thanks for the comment. I was not sure about the content of his loop, so I tried to explain why it does not work *as is*. The regression part comes from a question the OP asked earlier today with the same code, which he called "regression", hence my explanation why `parfor` will not work for regression. Since that is not the case here, I will remove that part from my post. – Adriaan Oct 27 '15 at 14:10
  • Since the OP explicitly asks *what's going on?* I explained that to him. – Adriaan Oct 27 '15 at 14:34
1

@Andras Deak put this in a comment, but the fix here is really simple - all you need to do is use a form of indexing for the second subscript to coef that is allowed by parfor. In this case, you need to do:

parfor i = ...
    coef(i, :) = ...;
end
Edric
  • 23,676
  • 2
  • 38
  • 40
  • I would also add that for this to work you have to pre-allocate with the proper size, since in the original question of OP there was `coef = zeros(n,10)` which would be incompatible with the length-18 vector returned by the `fit` (though this has since been edited in the question). – Andras Deak -- Слава Україні Oct 27 '15 at 13:51
  • Actually, you don't need to preallocate `coef` for this to work. Try: `clear x, parfor idx = 1:3, x(idx, :) = rand(1,2); end, x` for example. – Edric Oct 28 '15 at 09:12
  • I would think so, yes, but preallocating with the wrong size (as was originally in OP's version) would give an error. Wouldn't it? – Andras Deak -- Слава Україні Oct 28 '15 at 10:25