arrayfun

Apply function to each element of array on GPU

Description

example

Note

This function behaves similarly to the MATLAB® function arrayfun, except that the evaluation of the function happens on the GPU, not on the CPU. Any required data not already on the GPU is moved to GPU memory. The MATLAB function passed in for evaluation is compiled and then executed on the GPU. All output arguments are returned as gpuArray objects. You can retrieve gpuArray data using the gather function.

B = arrayfun(FUN,A) applies the function FUN to each element of the gpuArray A. arrayfun then concatenates the outputs from FUN into output gpuArray B. B is the same size as A and B(i,j,...) = FUN(A(i,j,...)). The input argument FUN is a function handle to a MATLAB function that takes one input argument and returns a scalar value. FUN is called as many times as there are elements of A.

You cannot specify the order in which arrayfun calculates the elements of B or rely on them being done in any particular order.

example

B = arrayfun(FUN,A1,...,An) applies FUN to the elements of the arrays A1,...,An, so that B(i,j,...) = FUN(A1(i,j,...),...,An(i,j,...)). The function FUN must take n input arguments and return a scalar. The nonsingleton dimensions of the inputs A1,...,An must all match, or the inputs must be scalar. Any singleton dimensions or scalar inputs are virtually replicated before being input to the function FUN.

example

[B1,...,Bm] = arrayfun(FUN,___) returns multiple output arrays B1,...,Bm when the function FUN returns m output values. arrayfun calls FUN each time with as many outputs as there are in the call to arrayfun, that is, m times. If you call arrayfun with more output arguments than supported by FUN, MATLAB generates an error. FUN can return output arguments having different data types, but the data type of each output must be the same each time FUN is called.

Examples

collapse all

In this example, a small function applies correction data to an array of measurement data. The function defined in the file myCal.m is shown here.

function c = myCal(rawdata, gain, offset)
    c = (rawdata .* gain) + offset;
end

The function performs only element-wise operations when applying a gain factor and offset to each element of the rawdata array.

Create a nominal measurement.

meas = ones(1000)*3; % 1000-by-1000 matrix

The function allows the gain and offset to be arrays of the same size as rawdata, so that unique corrections can be applied to individual measurements. In a typical situation, you can keep the correction data on the GPU so that you do not have to transfer it for each application:

gn   = rand(1000,'gpuArray')/100 + 0.995; 
offs = rand(1000,'gpuArray')/50  - 0.01;

Run your calibration function on the GPU.

corrected = arrayfun(@myCal,meas,gn,offs);

The function runs on the GPU because the input arguments gn and offs are already in GPU memory. The input array meas is converted to a gpuArray before the function runs.

Retrieve the corrected results from the GPU to the MATLAB workspace.

results = gather(corrected);

You can define a MATLAB function as follows.

function [o1,o2] = aGpuFunction(a,b,c)
    o1 = a + b;
    o2 = o1 .* c + 2;
end

Evaluate this function on the GPU.

s1 = rand(400,'gpuArray');
s2 = rand(400,'gpuArray');
s3 = rand(400,'gpuArray');
[o1,o2] = arrayfun(@aGpuFunction,s1,s2,s3);
whos
 Name        Size         Bytes  Class

  o1        400x400          108  gpuArray
  o2        400x400          108  gpuArray
  s1        400x400          108  gpuArray
  s2        400x400          108  gpuArray
  s3        400x400          108  gpuArray
Use gather to retrieve the data from the GPU to the MATLAB

Use gather to retrieve the data from the GPU to the MATLAB workspace.

d = gather(o2);

The function myfun.m generates and uses a random number R.

function y = myfun(x)
    R = rand();
    Y = R.*X;
end

If you use arrayfun to run this function with an input variable that is a gpuArray, the function runs on the GPU. The size of X determines the number of random elements to generate. The following code passes the gpuArray matrix G to myfun on the GPU.

G = 2*ones(4,4,'gpuArray')
H = arrayfun(@myfun, G)

Because G is a 4-by-4 gpuArray, myfun generates 16 random value scalar elements for R, one for each calculation with an element of G.

Input Arguments

collapse all

Function to apply to the elements of the input arrays, specified as a function handle. FUN must return scalar values. For each output argument, FUN must return values of the same class each time it is called. FUN must accept numerical or logical input data.

FUN must be a handle to a function that is written in the MATLAB language. You cannot specify FUN as a handle to a MEX-function.

FUN can contain the following built-in MATLAB functions and operators.

abs
and
acos
acosh
acot
acoth
acsc
acsch
asec
asech
asin
asinh
atan
atan2
atanh
beta
betaln
bitand
bitcmp
bitget
bitor
bitset
bitshift
bitxor
ceil
complex
conj
cos
cosh
cot
coth
csc
csch
double
eps
eq
erf
erfc
erfcinv
erfcx
erfinv
exp
expm1
false
fix
floor
gamma
gammaln
ge
gt
hypot
imag
Inf
int8
int16
int32
int64
intmax
intmin
isfinite
isinf
isnan
ldivide
le
log
log2
log10
log1p
logical
lt
max
min
minus
mod
NaN
ne
not
or
pi
plus
pow2
power
rand
randi
randn
rdivide
real
reallog
realmax
realmin
realpow
realsqrt
rem
round
sec
sech
sign
sin
single
sinh
sqrt
tan
tanh
times
true
uint8
uint16
uint32
uint64
xor


+
-
.*
./
.\
.^
==
~=
<
<=
>
>=
&
|
~
&&
||
Scalar expansion versions of the following:
*
/
\
^
Branching instructions:
break
continue
else
elseif
for
if
return
while

FUN can contain the random number generator functions rand, randi, and randn. However, the GPU does not support the complete functionality that MATLAB does.

The following syntaxes are supported for random matrix generation on the GPU.

rand
rand()
rand('single')
rand('double')
randn
randn()
randn('single')
randn('double')
randi
randi()
randi(IMAX, ...)
randi([IMIN IMAX], ...)
randi(..., 'single')
randi(..., 'double')
randi(..., 'int32')
randi(..., 'uint32')

You do not specify the array size for random generation. Instead, the number of generated random values is determined by the sizes of the input variables to your function. Enough random number elements are generated to satisfy the needs of your input or output variables. Arrays of random numbers have independent substreams for each element.

For more information about generating random numbers on the GPU, see Random Number Streams on a GPU.

Input array, specified as scalars, vectors, matrices, or multidimensional arrays. At least one input array argument must be a gpuArray for arrayfun to run on the GPU. Each array that is stored in CPU memory is converted to a gpuArray before the function is evaluated. If you plan to make several calls to arrayfun with the same array, it is more efficient to convert that array to a gpuArray.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical

Output Arguments

collapse all

Output array, returned as a gpuArray.

Tips

  • The first time you call arrayfun to run a particular function on the GPU, there is some overhead time to set up the function for GPU execution. Subsequent calls of arrayfun with the same function can run faster.

  • Nonsingleton dimensions of input arrays must match each other. In other words, the corresponding dimensions of arguments A1,...,An, must be equal to each other, or equal to one. Whenever a dimension of an input array is singleton (equal to 1), arrayfun uses singleton expansion. The array is virtually replicated along the singleton dimension to match the largest of the other arrays in that dimension. When a dimension of an input array is singleton and the corresponding dimension in another argument array is zero, arrayfun virtually diminishes the singleton dimension to 0.

    Each dimension of the output array B is the same size as the largest of the input arrays in that dimension for nonzero size, or zero otherwise. The following code shows how dimensions of size 1 are scaled up or down to match the size of the corresponding dimension in other arguments.

    R1 = rand(2,5,4,'gpuArray');
    R2 = rand(2,1,4,3,'gpuArray');
    R3 = rand(1,5,4,3,'gpuArray');
    R = arrayfun(@(x,y,z)(x+y.*z),R1,R2,R3);
    size(R)
    
      2     5     4     3
    R1 = rand(2,2,0,4,'gpuArray');
    R2 = rand(2,1,1,4,'gpuArray');
    R = arrayfun(@plus,R1,R2);
    size(R)
    
      2     2     0     4
    
  • Because the operations supported by arrayfun are strictly element-wise, and each computation of each element is performed independently of the others, certain restrictions are imposed:

    • Input and output arrays cannot change shape or size.

    • Functions such as rand do not support size specifications. Arrays of random numbers have independent streams for each element.

  • Like arrayfun in MATLAB, matrix exponential power, multiplication, and division (^, *, /, \) perform element-wise calculations only.

  • Operations that change the size or shape of the input or output arrays (cat, reshape, and so on), are not supported.

  • Read-only indexing (subsref) and access to variables of the parent (outer) function workspace from within nested functions is supported. You can index variables that exist in the function before the evaluation on the GPU. Assignment or subsasgn indexing of these variables from within the nested function is not supported. For an example of the supported usage, see Stencil Operations on a GPU

  • Anonymous functions do not have access to their parent function workspace.

  • Overloading the supported functions is not allowed.

  • The code cannot call scripts.

  • There is no ans variable to hold unassigned computation results. Make sure to explicitly assign to variables the results of all calculations.

  • The following language features are not supported: persistent or global variables, parfor, spmd, switch, and try/catch.

  • P-code files cannot contain a call to arrayfun with gpuArray data.

Introduced in R2010b