Main Content

arrayfun

関数を GPU 上の配列内の各要素に適用する

説明

メモ

この関数の動作は MATLAB® 関数 arrayfun と似ていますが、関数の評価が CPU ではなく GPU で行われる点で異なります。まだ GPU 上にない必要なデータは GPU メモリに移動されます。評価のために渡された MATLAB 関数がコンパイルされてから GPU で実行されます。すべての出力引数は gpuArray オブジェクトとして返されます。関数 gather を使用して gpuArray データを取得できます。

B = arrayfun(FUN,A) は、関数 FUNgpuArray A の各要素に適用します。次に arrayfunFUN の出力を連結して gpuArray B の出力を生成します。BA と同じサイズであり、B(i,j,...) = FUN(A(i,j,...)) です。入力引数 FUN は、1 つの入力引数を受け入れ、スカラー値を返す MATLAB 関数の関数ハンドルです。FUN は、A の要素数と同じ回数呼び出されます。

arrayfun での B の要素の計算順序を指定したり、特定の順序で計算される要素に依存したりすることはできません。

B = arrayfun(FUN,A1,...,An) は、B(i,j,...) = FUN(A1(i,j,...),...,An(i,j,...)) となるように FUN を配列 A1,...,An の要素に適用します。関数 FUN は、n 個の入力引数を受け入れてスカラーを返さなければなりません。入力 A1,...,An の大きさが 1 でない次元がすべて一致しなければなりません。あるいは、入力がスカラーでなければなりません。大きさが 1 の次元、すなわちスカラー入力は、関数 FUN に入力される前に実質的に複製されます。

[B1,...,Bm] = arrayfun(FUN,___) は、関数 FUNm 個の出力値を返す場合に複数の出力配列 B1,...,Bm を返します。arrayfun は毎回、arrayfun の呼び出しにおける出力の数と同じ回数、すなわち mFUN を呼び出します。FUN でサポートされる数より多くの出力引数を指定して arrayfun を呼び出した場合、MATLAB はエラーを生成します。FUN は異なるデータ型をもつ出力引数を返すことができますが、FUN の各呼び出しにおいて、各出力のデータ型は同じでなければなりません。

すべて折りたたむ

次の例では、小さな関数で測定データの配列に補正データを適用しています。ファイル myCal.m で定義されている関数を以下に示します。

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

この関数は、rawdata 配列の各要素にゲイン係数とオフセットを適用する際に、要素単位の演算のみを実行します。

ノミナル測定値を作成します。

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

この関数では、ゲインとオフセットを rawdata と同じサイズの配列にすることができ、個々の測定値に一意の補正を適用できます。通常は、補正データを GPU 上に保持することができるため、適用のたびに補正データを転送せずに済みます。

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

GPU でキャリブレーション関数を実行します。

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

この関数は、入力引数 gn および offs が既に GPU メモリ上に格納されているため GPU で実行されます。関数が実行される前に、入力配列 measgpuArray に変換されます。

補正された結果を GPU から MATLAB ワークスペースに取得します。

results = gather(corrected);

MATLAB 関数を次のように定義できます。

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

この関数を 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       Attributes

  o1        400x400            1280000  gpuArray              
  o2        400x400            1280000  gpuArray              
  s1        400x400            1280000  gpuArray              
  s2        400x400            1280000  gpuArray              
  s3        400x400            1280000  gpuArray              

gather を使用して、GPU から MATLAB ワークスペースにデータを取得します。

d = gather(o2);

関数 myfun.m は乱数 R を生成して使用します。

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

arrayfun を使用し、gpuArray である入力変数を指定してこの関数を実行すると、関数は GPU で実行されます。生成される乱数の要素数は X のサイズによって決まります。次のコードでは、gpuArray 行列 G を GPU 上の myfun に渡しています。

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

G は 4 行 4 列の gpuArray であるため、myfunR の 16 個の乱数値スカラー要素 (G の各要素との計算につき 1 つ) を生成します。

入力引数

すべて折りたたむ

入力配列の要素に適用する関数。関数ハンドルとして指定します。FUN はスカラー値を返さなければなりません。各出力引数について、FUN は呼び出されるたびに同じクラスの値を返さなければなりません。FUN は数値または logical の入力データを受け入れなければなりません。

FUN は MATLAB 言語で記述された関数のハンドルでなければなりません。FUN を MEX 関数のハンドルとして指定することはできません。

FUN には、以下の MATLAB の組み込み関数および演算子を含めることができます。

abs
and
acos
acosh
acot
acoth
acsc
acsch
asec
asech
asin
asinh
atan
atan2
atanh
beta
betaln
bitand
bitcmp
bitget
bitor
bitset
bitshift
bitxor
cast
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
ones
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
zeros

+
-
.*
./
.\
.^
==
~=
<
<=
>
>=
&
|
~
&&
||

以下のスカラー拡張バージョン:

*
/
\
^
分岐命令:
break
continue
else, elseif, if
for
return
switch, case, otherwise
while

配列を作成する関数 (InfNaNonesrandrandirandnzeros など) は、サイズ指定を入力引数としてサポートしていません。代わりに、生成される配列のサイズは、関数の入力変数のサイズによって決まります。入力変数または出力変数の要求を満たす十分な数の配列要素が生成されます。クラスと "like" の両方の構文を使用して、データ型を指定できます。以下の例で、配列作成関数でサポートされる構文を示します。

a = rand;
b = ones();
c = zeros("like", x);
d = Inf("single");
e = randi([0 9], "uint32");

FUN 内で randrandi および randn を使用して乱数を生成する場合、各要素は異なるサブストリームから生成されます。GPU での乱数発生の詳細については、GPU 上の乱数ストリームを参照してください。

FUN の内部で switch, case, otherwise を使用する場合、次の制限があります。

  • ケース式は数値と logical 値のみをサポートします。

  • スイッチ式を複数の値と比較するために、cell 配列をケース式として使用すること (たとえば case {x1,y1}) はサポートされていません。

入力配列。スカラー、ベクトル、行列または多次元配列として指定します。arrayfun を GPU 上で実行するには、少なくとも 1 つの入力配列の引数が gpuArray でなければなりません。CPU メモリに格納された各配列は、関数が評価される前に gpuArray に変換されます。同じ配列を指定して arrayfun を複数回呼び出す場合、その配列を gpuArray に変換するとより効率的になります。

データ型: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | logical

出力引数

すべて折りたたむ

出力配列。gpuArray として返されます。

ヒント

  • GPU で特定の関数を呼び出すために最初に arrayfun を呼び出す時点では、GPU 実行のための関数の設定に若干のオーバーヘッド時間が発生します。同じ関数を指定したその後の arrayfun の呼び出しでは、処理速度が向上します。

  • 入力配列の大きさが 1 でない次元は他の入力配列の大きさが 1 でない次元と一致しなければなりません。つまり、対応する引数の次元 A1,...,An はサイズが互いに等しいか、1 でなければなりません。入力配列の次元がシングルトン (1 と等価) である場合は常に、arrayfun はシングルトン拡張を使用します。大きさが 1 の次元に沿って配列を実質的に複製し、その次元のサイズを最大の他の配列と一致させます。入力配列の 1 つの次元の大きさが 1 で、別の引数配列の対応する次元がゼロである場合、arrayfun は実質的に大きさが 1 の次元を 0 に減じます。

    出力配列 B の各次元は、非ゼロ サイズの次元では入力配列のうち最大の配列と同じサイズに、それ以外ではゼロになります。次のコードは、サイズ 1 の次元を、他の引数内の対応する次元のサイズと一致させるためにどのように増減しているかを示します。

    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
    
  • arrayfun によりサポートされている演算は厳密に要素単位であり、各要素の各計算は他の要素と独立して実行されるため、一定の制約が適用されます。

    • 入出力配列の形状やサイズは変更できません。

    • rand などの配列作成関数は、サイズ指定をサポートしていません。乱数の配列は、要素ごとに独立したストリームを有しています。

  • MATLAB の arrayfun と同様に、行列のべき乗、乗算および除算 (^*/\) では要素単位の計算のみが実行されます。

  • 入出力配列 (catreshape など) のサイズまたは形状を変更する演算はサポートされていません。

  • 読み取り専用のインデックス付け (subsref) と、入れ子関数の中から親 (外側) 関数ワークスペースの変数へのアクセスがサポートされています。GPU で関数を評価する前に、その関数内にある変数にインデックスを付けることができます。入れ子関数の中からこのような変数を代入したりそれを subsasgn インデックス化することは、サポートされません。サポートされている使用法の例は、GPU でのステンシル演算を参照してください。

  • 無名関数はその親関数のワークスペースにはアクセスできません。

  • サポートされている関数のオーバーロードは許可されません。

  • コードからスクリプトを呼び出すことはできません。

  • 代入されていない計算結果を格納する ans 変数はありません。必ずすべての計算結果を明示的に変数に代入します。

  • サポートされていない言語機能として、永続変数またはグローバル変数、parforspmdtry および catch が挙げられます。

  • P コード ファイルに、gpuArray データがある arrayfun の呼び出しを含めることはできません。

バージョン履歴

R2010b で導入

すべて展開する