arrayfun with a function that has 5 inputs of different dimension

3 Ansichten (letzte 30 Tage)
Guilhem Chaumont
Guilhem Chaumont am 1 Jun. 2016
Bearbeitet: Joss Knight am 8 Jun. 2016
Hello everyone,
I have written a code to perform a gradient descent function on each point of a big set of values (~100k-2m points). It performs as expected but handles only one point at a time and I would like to speed it up. It seems that a good way to do it would be to perform the function on 384 points at the same time on the 384 cores of my gpu, using arrayfun.
However, after days of searches and tries, I cannot make it work using arrayfun. Maybe this comes from the fact that my function has 5 inputs with different dimensions:
function [Theta[150x1], J_history[20x1]] = GradientDescentLinear(X[1500x150], ...
Y[1500x 1], ...
Theta[150x1], ...
Alpha[1x 1], ...
Num_iters[1x1])
I have tried several things, for instance adding a 3rd [x384] dimension to all the inputs with the right values.but when I run :
[A,B] = arrayfun(GradientDescentLinear, ...
gX_TrainingSetCell, ...
gY_TrainingSetCell, ...
gTheta, ...
gAlpha, ...
gNum_iters);
I alaways get the same error:
Not enough input arguments.
Error in GradientDescentLinear(line 5)
m = (length(Y)); % number of training examples
I have also tried to turn the 5 inputs into 5 [384x1] cells containing the matrices, vector or values. But it does not work (altough it would haven't been possible to then send the cells to the GPU).
Can anyone help me with this? If you know an other way to do this I am also very interested. I can provide more informations if necesseray.
I would like to thank you for your help and your time,
Guilhem
  2 Kommentare
dpb
dpb am 1 Jun. 2016
From
help arrayfun
...
A = arrayfun(FUN, B, C, ...) evaluates FUN using elements of arrays B,
C, ... as input arguments. The (I,J,...)th element of A is equal to
FUN(B(I,J,...), C(I,J,...), ...). B, C, ... must all have the same size.
The purpose of arrayfun is to apply a given function to each and every element of the corresponding array elements of each array. Hence, your case of having differing array sizes is just the wrong tool.
bsxfun handles singleton expansion for two-element functions saving an explicit repmat, but that doesn't match your case, either.
You'll have to figure out ways to tile the data to be symmetric in order to be able to factor this; otomh w/o knowing more than we do, don't know we've got the ability to judge whether that's feasible or even possible.
Guilhem Chaumont
Guilhem Chaumont am 2 Jun. 2016
Thank you dpb, it is clear now that arrayfun will definitely not work in my case, I am now aiming to find a more "traditional" work around using simple matrix multiplication.

Melden Sie sich an, um zu kommentieren.

Antworten (1)

Walter Roberson
Walter Roberson am 1 Jun. 2016
[A,B] = arrayfun(@GradientDescentLinear, ... %notice @
gX_TrainingSetCell, ...
gY_TrainingSetCell, ...
gTheta, ...
gAlpha, ...
gNum_iters);
  2 Kommentare
Guilhem Chaumont
Guilhem Chaumont am 2 Jun. 2016
Bearbeitet: Guilhem Chaumont am 2 Jun. 2016
Thank you very much for all your help. I think I am getting closer. What would solve all my problems would be the following. In the original point by point function I have a linear hypothesis function that takes a [10x5] input matrix features and multiply it with a linear regression vector that is [5x1]. The result is a list of 10 hypothesis values:
A=ones(10,5);
B=ones(5,1);
C=A*B; [10,1]
This work perfectly well. Now creating the matrix for the 384 instead of 1 points is easy and I have as a result:
A=ones(10,5,384)
B=ones(5,384)
However I cannot simply again multiple the two matrix. What I am trying to achieve is to multiply each 2d array of A with the corresponding column of B. On trick I tried was:
A = ones(10,5,384) ;
B = ones(5,384) ;
fun = @(A,B,n) A(:,:,n)*B(:,n) ;
C = fun(A,B,1:384) ; [10x384?]
But Matlab does not understand what I am trying to achieve as it returns:
Error using *
Inputs must be 2-D, or at least one input must be scalar.
To compute elementwise TIMES, use TIMES (.*) instead.
Error in Untitled>@(A,B,n)A(:,:,n)*B(:,n)
Error in Untitled (line 6)
C = fun(A,B,1:384) ;
If instead of (1:384) i enter a single value like 45 it works well which suggest everything would be fine with a for loop but if I am not misunderstanding, I would loose the advantage of the multi cores of the GPU, right?
Any idea on how to achieve this? Again, many thanks for your help.
Joss Knight
Joss Knight am 8 Jun. 2016
Bearbeitet: Joss Knight am 8 Jun. 2016
You can't do matrix operations inside GPU arrayfun. Use pagefun instead. Make A 10x5x384 and B 5x1x384, then you can call
C = pagefun(@mtimes, A, B);
C will now be 10x1x384.
It seems like you've picked 384 because it's the reported number of cores on your GPU. GPU parallelism doesn't work that way, so forget about that number. Just make the 3rd dimension as large as you can and the GPU will take care of scheduling the work.
To use arrayfun to do 384 complex vector operations per thread, you have to:
  1. Write out all the matrix algebra in your arrayfun function manually using scalar arithmetic and loops.
  2. Send your arrays into the function as up-level variables, i.e. variables declared outside the scope of a nested function that can be accessed from inside.
  3. Pass a single vector, e.g. 1:384, as an argument to your arrayfun function in order to instruct it to launch 384 threads.
  4. Index into your complex arrays inside the function one value at a time.
  5. Return an output that is the same size as your input - i.e. your function can only return one value per thread.
In other words, don't do it! That's what all the optimized matrix and vector routines that MATLAB provides for you are designed to do.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by