4

I am having issues using arrayfun in MATLAB using GPU processing. I have simplified my situation below.

I have 4 large matrices (video data as (x,y,t)). Ill use random for this example.

A = gpuArray(rand(10,10,100));
B = gpuArray(rand(10,10,100));
C = gpuArray(rand(10,10,100));
D = gpuArray(rand(10,10,100));

I wish to take each pixel of each matrix;(1,1,1) then (2,1,1) etc; and perform the least squares calculation (values are examples)

X = [10 10 ; 20 20 ; 30 30 ; 40 40]\[A;B;C;D];

Performing this as a for loop takes too long for my data. Since I want to perform a function on each element individually I thought using the GPU would be the way to go.

To do this I created the function

function [x] = GPUTestFun (A,B,C,D)
X = [10 10 ; 20 20 ; 30 30 ; 40 40]\[A;B;C;D];
end

Which I then call with arrayfun (I don't think matlab has GPU support for leastsquares?)

[x] = arrayfun(@GPUTestFun,[A;B;C;D]);

My understanding is that this should take each element of the 4 matricies individually and perform the calculations.

The error I get it: Error using gpuArray/arrayfun Array concatenation is not supported. error at line: 4.

Line 4 being :

X = [10 10 ; 20 20 ; 30 30 ; 40 40]\[A;B;C;D];

Its obvious that the issue is that I am concatenating the matrix within the arrayfun. I have thought about what my options are and cant seem to see a solution. I considered concatenating the matrices before I call the function, however array fun will try to perform the function on every element, which now wont line up. I considered maybe solving the least squares manually rather than using \, however am hesitant to attempt this without checking if I've missed an easier solution first.

I also realise the output X will probably need tweaking since the single calculation produces 2 outputs, so will probably need to separate these so my outputs are the same size as my inputs. This isn't the current issue however.

Any help will be greatly appreciated.

Thanks Jordan

EDIT: Working CPU code:

A = (rand(10,10,100));
B = (rand(10,10,100));
C = (rand(10,10,100));
D = (rand(10,10,100));

[X1,X2] = arrayfun(@GPUTestFun,A,B,C,D);

Function:

function [X1,X2] = GPUTestFun (A,B,C,D)
    [X] = [10 11 ; 20 8 ; 30 30 ; 40 30]\[A;B;C;D];
    X1 = X(1);
    X2 = X(2);
end
4
  • I'm not quite clear what you're trying to achieve here - could you show a working CPU version of the code? Your original line calculating X doesn't work even for CPU data... Commented May 20, 2015 at 7:46
  • Can you try to create a new matrix, E that consists of size(E)=size([A;B;C;D])? Additionally, the ` \ ` operator does A LOT OF THINGS. Some of them iterative and not ready for GPU computing, so most likely you are not going to get any advantage (even if it is possible to make ` \ ` in the GPU, eich i am not sure) Commented May 20, 2015 at 10:16
  • @Edric Thanks for your reply. You're right that it doesn't quite work for CPU. I have made a few changes and added the working CPU code. When I do convert to GPU I get the same issue. "Array concatenation is not supported." So I guess my issue can be summarized as: Is there a way to concatenate in arrayfun GPU processing? Or is there a way around it? Commented May 21, 2015 at 1:33
  • @Ander Biguri Thanks for suggestion. Do you mean create the matrix within the function? I don't think I can. I tried N = zeros(size(4,1)); Zeros (and presumably other matrix creates are not supported. also N(1) =1; N(2)=2...etc. But Array indexing is not supported either. If you meant create the matrix outside the function, then my issue is that arrayfun will try to perform the action on every element. so having a single matrix wont work. Perhaps where is a way to perform arrayfun down only one dimension? I think this might be a way around it, and pass 4x10000 matrix in. Ill play around more. Commented May 21, 2015 at 1:52

1 Answer 1

3

In this case, you can simply recast the whole problem as a multiple-right-hand-side call to \, like so:

%# with A,B,C,D defined as per question
AA = [10 11 ; 20 8 ; 30 30 ; 40 30];
x  = [A(:)'; B(:)'; C(:)'; D(:)'];
x1x2 = AA \ x;
X1 = reshape(x1x2(1,:), size(A));
X2 = reshape(x1x2(2,:), size(A));

This will work on the GPU.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much @Edric. I tried applying the \ function in that way so it performs the way you have shown, but must have made a mistake somewhere. Using Arrayfun seems to have been the issue due to the need to concatenate within the function. I now have issues with memory, as my A,B,C,D matricies are 280x260x15000 each. But I'll do some more research as to not change the topic of this question.Thanks again. Jordan

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.