生成コードでの 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