Main Content

カーネル解析

GPU コード生成では、CUDA® カーネルを作成するための基本となるメカニズムは for ループを使用することです。MATLAB® コード内でのループの書き方は、作成されるカーネル数と、生成コードのパフォーマンスに大きく影響します。GPU コードを生成する場合、診断レポートをチェックし、ループ セグメントに Loop not parallelized という注意が表示されているかどうかを確認します。コード内の MATLAB 関数への呼び出しにも、これらの注意が含まれる for ループがある可能性があります。パフォーマンスを最大化するには、コード内の計算量の多いループ セグメントがカーネルにマッピングされ、並列に実行されていることを確認する必要があります。以降の推奨事項は、この目標を達成し、効率的な CUDA カーネルを生成するのに役立ちます。

カーネルに対する入れ子にされたループのマッピング

条件

入れ子にされた for ループを含む関数について考えます。

function y = foo(x)
 ...
 for i1 = 1:N1
  for i2 = 1:N2
   for i3 = 1:N3
    for i4 = 1:N4
     ...
    end
   end
  end
 end

中間ループの 1 つである i3 を並列化できないとします。ループ解析を実行してカーネルを作成すると、GPU Coder™ では最も外側の並列ループ i1,i2 のみが考慮され、外側のループ次元 N1,N2 のカーネルが作成されます。ループ i3,i4 はカーネル本体内にあり、逐次的に実行されます。ただし、最も内部の i4 が大きい (反復である) 場合、最も内部のループ用にカーネルを作成することで、より優れたパフォーマンスが達成される可能性があります。

操作

次の 3 つの方法で、最も内部のループを並列化することができます。

  • コードを書き直し、最も内部のコード セグメントが、入れ子にされたループ内に入らないようにします。

  • 外側のループの反復サイズが小さい場合、このループを関数 coder.unroll に追加します。この関数は、各ループ反復でループ本体のコピーを作成することにより、for ループを展開します。詳細については、coder.unroll を参照してください。

    function y = foo(x)
     ...
     for i1 = coder.unroll(1:N1)
      ...
     end
  • 外側のループ次元を動的な範囲にします。このようにすると、外側のループでの並列ループ解析は失敗しますが、内側のループでは成功します。

    function y = foo(x,N1)
     ...
     for i1 = 1:N1
      ...
     end

break を含む for ループ

条件

break を含むループはサポートされません。

while (i < N)
	...
	...
	if (cond2)
		...
		...
		break;
	end
end

操作

ガード変数および条件を作成して break を削除します。

cond = true;
while (i< N)
	if(cond)
		...
		...
		if(cond2)
			cond = false;
		end
	end
end

依存性解析の並列ループ チェックの失敗

条件

カーネル抽出では並列ループの依存性解析が使用されます。ループの依存性解析で並列 for ループを検出できない場合があります。coder.gpu.kernel は、GPU Coder で依存性解析をオーバーライドし、強制的にカーネルを作成できるようにします。注意点として、ユーザーはそのループが反復間で依存関係を持たない "for-all" ループであることを確認してください。

操作

各 for ループに対して明示的に coder.gpu.kernel プラグマを使用します。

配列の論理インデックス付け

条件

配列要素へのアクセスのために論理インデックスが使用されていない場合、GPU Coder ではカーネルが作成されない可能性があります。

i = (mag ~= 0);
vx(i) = vx(i)./mag(i);
vy(i) = vy(i)./mag(i); 

操作

ループ本体を使用して適切な条件で保護することで、コードを書き換えます。

for i = 1:numel(mag)
 if (mag(i) ~= 0)
    vx(i) = vx(i)./mag(i);
    vy(i) = vy(i)./mag(i);  
 end
end 

サポートされない関数

条件

サポートされない関数、コーダー プラグマ、ツールボックス関数などをループ内部で使用していると、カーネル化することができなくなります。

操作

純粋な MATLAB を使用して、サポートされない関数を書き換えてみます。

ループの交換

条件

ループの入れ子内で比較的小さいループが最も外側のループになっている場合、その入れ子に含まれているループの一部のみでカーネルが作成される可能性があります。アルゴリズムで許容される場合、常に最も外側の入れ子に最も大きなループを配置してください。

操作

より大きなループをより外側のループにしてループの入れ子を書き換えます。

関連するトピック