arrayfun を使用した、要素単位の MATLAB® 関数の GPU におけるパフォーマンス改善
この例では、arrayfun
を使用して MATLAB® 関数を GPU でネイティブに実行する方法を説明します。MATLAB 関数に要素単位の演算が多数含まれている場合、arrayfun
を使用すると、gpuArray 入力データを用いて MATLAB 関数を GPU で直接実行する場合に比べパフォーマンスを改善できます。MATLAB 関数は独自のファイルに入れるか、あるいは入れ子関数や無名関数とすることができます。関数に含まれるのはスカラー演算と算術演算に限られます。
例を関数に配置して、入れ子関数を可能にします。
function paralleldemo_gpu_arrayfun
Horner 法を使用した指数の計算
Horner 法では、べき級数展開を効率的に評価できます。これを使用して、指数関数 exp
のべき級数展開の最初の 10 項を計算します。これは MATLAB 関数として実装できます。
function y = horner(x) %HORNER - series expansion for exp(x) using Horner's rule y = 1 + x.*(1 + x.*((1 + x.*((1 + ... x.*((1 + x.*((1 + x.*((1 + x.*((1 + ... x.*((1 + x./9)./8))./7))./6))./5))./4))./3))./2)); end
horner
を GPU で使用するための準備
最小限のコード変更でこの関数を GPU で実行するために、gpuArray
オブジェクトを入力として関数 horner
に渡すことができます。horner
には要素単位の個別の演算のみが含まれているため、各演算を 1 つずつ実行すると、GPU でさほど優れたパフォーマンスを実現できない可能性があります。しかし、arrayfun
を使用して関数 horner
内の要素単位の演算をすべて一度に実行することで、パフォーマンスを改善できます。
arrayfun
を使用して GPU でこの関数を実行するために、関数 horner
のハンドルを使用します。horner
は、異なるサイズと型の入力に自動的に適応します。関数を直接評価するだけで、gpuArray
オブジェクトと arrayfun
の両方を使用して GPU で計算された結果を、標準 MATLAB の CPU での実行と比較できます。
hornerFcn = @horner;
入力データの作成
型とサイズの異なるいくつかの入力を作成し、gpuArray
を使用して GPU に送信します。
data1 = rand( 2000, 'single' ); data2 = rand( 1000, 'double' ); gdata1 = gpuArray( data1 ); gdata2 = gpuArray( data2 );
GPU での horner
の評価
GPU で関数 horner
を評価するには、2 つの選択肢があります。gpuArray
オブジェクトを入力として指定することにより、最小限のコード変更で元の関数を GPU で評価できます。しかし、GPU でのパフォーマンスを高めるために、元の MATLAB 関数と同じ呼び出し規則を使用して arrayfun
を呼び出します。
結果の精度を比較するには、CPU を使った MATLAB で元の関数を直接評価します。GPU の浮動小数点演算は CPU で実行される演算と正確には一致しないため、数値はわずかに異なると予想されます。
gresult1 = arrayfun( hornerFcn, gdata1 ); gresult2 = arrayfun( hornerFcn, gdata2 ); comparesingle = max( max( abs( gresult1 - horner( data1 ) ) ) ); comparedouble = max( max( abs( gresult2 - horner( data2 ) ) ) );
fprintf( 'Maximum discrepancy for single precision: %g\n', comparesingle ); fprintf( 'Maximum discrepancy for double precision: %g\n', comparedouble );
Maximum discrepancy for single precision: 2.38419e-07 Maximum discrepancy for double precision: 0
GPU と CPU のパフォーマンスの比較
GPU バージョンのパフォーマンスを、ネイティブの MATLAB CPU バージョンと比較できます。現在の世代の GPU は単精度でのパフォーマンスにおいてずっと優れているため、これを比較します。
% CPU execution tic hornerFcn( data1 ); tcpu = toc; % GPU execution using only gpuArray objects tgpuObject = gputimeit(@() hornerFcn(gdata1)); % GPU execution using gpuArray objects with arrayfun tgpuArrayfun = gputimeit(@() arrayfun(hornerFcn, gdata1)); fprintf( 'Speed-up achieved using gpuArray objects only: %g\n',... tcpu / tgpuObject ); fprintf( 'Speed-up achieved using gpuArray objects with arrayfun: %g\n',... tcpu / tgpuArrayfun );
Speed-up achieved using gpuArray objects only: 24.6764 Speed-up achieved using gpuArray objects with arrayfun: 98.3555
end