生成コードでの for
ループの自動並列化
MATLAB® Coder™ は、生成される C/C++ コードにおいて、既定では Open Multiprocessing (OpenMP) ライブラリを使用して for
ループを自動的に並列化します。自動並列化では、明示的および暗黙的な for
ループとリダクション演算を実行する for
ループの並列化がサポートされます。詳細については、Reduction Operations Supported for Automatic Parallelization of for-loopsを参照してください。
並列の C/C++ コードを生成するには、コンパイラで OpenMP ライブラリがサポートされていなければなりません。自動並列化を有効にするオプションは、coder.config
関数のすべてのビルド タイプ (MEX、DLL、LIB、および EXE) をサポートしています。
MATLAB Coder は、内部のヒューリスティックな方法を使用して、for
ループを並列化すべきかどうかを判定します。
明示的および暗黙的な for
ループの並列化
for
ループの自動並列化では、明示的と暗黙的の両方の for
ループがサポートされます。生成された C/C++ コードで並列 for
ループを実行するためのCPU スレッドの最大数を指定できます。
詳細については、生成コードで並列 for ループを実行するための最大スレッド数の指定を参照してください。
明示的な for
ループの並列化
明示的な for
ループとは、MATLAB コードに存在している for
ループのことです。自動並列化により、配列の要素単位の演算で利点が得られます。次の表は、明示的な for
ループを含む MATLAB 関数と、自動並列化を使用して生成された C コードを示しています。コードを生成するには、MATLAB 関数を現在の作業ディレクトリに explicitLoop.m
として保存し、codegen
コマンドを実行します。
MATLAB コード | 生成した C コード |
---|---|
% MATLAB code function out = explicitLoop(a, b) out = zeros(size(a)); for i = 1:numel(a) if a(i) > 1000 out(i) = a(i) - b(i); else out(i) = a(i) + b(i); end end end % C code generation command >> codegen explicitLoop -args {1:10000, 1:10000} -config:lib -report |
|
暗黙的な for
ループの並列化
暗黙的な for
ループとは、MATLAB コードでは記述されていませんが、生成される C/C++ コードで for
ループに変換される MATLAB 演算のことです。次の表は、暗黙的な for
ループを含む MATLAB 関数と、自動並列化を使用して生成された C コードを示しています。コードを生成するには、MATLAB コードを現在の作業ディレクトリに implicitLoop.m
として保存し、codegen
コマンドを実行します。
MATLAB コード | 生成した C コード |
---|---|
% MATLAB code function [y]= implicitLoop(in) a = ones(10000,1) + in; y = [a a]; end % C code generation command >> codegen implicitLoop -args {100} -config:lib -report |
|
ループのバージョン管理
上記の例では、ループ境界はコンパイル時の定数です。ループ境界がコンパイル時に不明な場合、コード ジェネレーターは逐次バージョンと並列バージョンの両方の for
ループを生成します。実行時のループの反復回数に応じて、より効率的なバージョンのループが実行されます。
次の表は、MATLAB 関数 loopVersion
と、逐次バージョンと並列バージョンの両方の for
ループを含む生成された C コードを示しています。
MATLAB コード | 生成した C コード |
---|---|
% MATLAB code function y = loopVersion(A, n) y = zeros(size(A)); for i = 1:n y(i) = sin(A(i)); end end % C code generation command >> codegen loopVersion -args {1:10000, 10000} -config:lib -report |
|
コード生成レポートとコード洞察
上記の MATLAB 関数 explicitLoop
の生成された C/C++ コードを確認するには、コード生成レポートを開きます。レポートの [コード] ペインで、for
ループの横にある緑色で強調表示された行番号はコードの並列化される部分を示しています。
生成コード
生成コードで、for
ループの前にある OpenMP プラグマ ステートメントは for
ループの並列化を示しています。
void explicitLoop(const double a[10000], const double b[10000],
double out[10000])
{
double d;
int i;
if (!isInitialized_explicitLoop) {
explicitLoop_initialize();
}
#pragma omp parallel for num_threads(omp_get_max_threads()) private(d)
for (i = 0; i < 10000; i++) {
d = a[i];
if (d > 1000.0) {
out[i] = d - b[i];
} else {
out[i] = d + b[i];
}
}
}
コード洞察
[コード洞察] タブの [自動並列化] で、生成コードにおいて並列化またはバージョン化されていない for
ループについての詳細情報を確認できます。
たとえば、入力引数に指定するサイズを小さくして、前に定義した explicitLoop
関数のコードを再度生成します。
>> codegen explicitLoop -args {1:100, 1:100} -config:lib -report
この場合、実行時にパフォーマンス上の利点は得られないため、for
ループは並列化されません。このようなコードの洞察を表示するには、コード生成レポートを開いて [コード洞察]、[自動並列化] をクリックします。
for
ループの並列化の制御
逐次実行の方が優れたパフォーマンスが得られる場合は、for
ループの自動並列化を無効にできます。
すべての for
ループの並列化を無効化
parfor
や coder.loop.parallelize("loopID")
が続くループの並列化は無効にできません。
すべての for
ループの自動並列化を無効にするには、次のようにします。
MATLAB Coder アプリで、[詳細設定]、[速度] ペインの [自動並列化を有効にする] 設定をオフにする。
MATLAB コマンド ウィンドウで、コード構成オプション
EnableAutoParallelization
をfalse
に設定する。
特定の for
ループの並列化を無効化
特定の for
ループを並列化しないようにするには、MATLAB コードでそのループの直前に coder.loop.parallelize("never")
を配置します。これは EnableAutoParallelization
設定をオーバーライドします。
たとえば、コード ジェネレーターは次のループを並列化しません。
coder.loop.parallelize("never"); for i = 1:n y(i) = y(i)*sin(i); end
特定の for
ループの並列化を有効化
特定の for
ループを並列化するには、MATLAB コードでその for
ループの直前に coder.loop.parallelize("loopID")
を配置します。これは EnableAutoParallelization
設定をオーバーライドします。
たとえば、次の for
ループは生成コードで常に並列化されます。
coder.loop.parallelize("i"); for i = 1:100 out1(i) = out1(i)*i; end
詳細については、coder.loop.parallelize
を参照してください。
使用上の注意および制限
入れ子にされた
for
ループの場合、MATLAB Coder は最も外側のfor
ループを並列化し、最も内側のfor
ループをベクトル化します。parfor
ループを含むfor
ループは並列化されません。自動並列化では、本体に永続変数または永続変数にアクセスする関数の呼び出しが含まれている
for
ループはサポートされません。自動並列化では、外部関数の呼び出しを含むコード内の
for
ループはサポートされません。while
ループは並列化されません。シングル コアのハードウェア ターゲットまたは
NumberOfCpuThreads
が1
に設定されたハードウェア ターゲットは自動的に並列化されません。OpenMP がターゲット ハードウェアでサポートされていない場合、または
coder.CodeConfig
オブジェクトのプロパティEnableOpenMPがfalse
に設定されている場合、いずれのfor
ループも並列化されません。単一レベルの
for
ループについて、ベクトル化と並列化が可能な場合はベクトル化されます。
参考
parfor
| coder.loop.parallelize
| coder.config
| coder.MexCodeConfig
| coder.CodeConfig
| coder.EmbeddedCodeConfig