このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
MATLAB での並列計算の基本操作
並列計算を使用して多数の計算を同時に実行できます。大規模な問題を小規模な問題に分割し、それらを同時に処理できます。
並列計算を使用して次のことが可能です。
タスクを分散して同時実行することで時間を節約
データを分割してビッグ データの問題を解決
デスクトップ コンピューターのリソースを利用してクラスターおよびクラウド コンピューティングにスケール アップ
次の表に、並列計算の基本的な用語とその定義の一部を示します。
用語 | 定義 |
---|---|
スレッド | CPU で個別にスケジューリングして実行できる最小の一連の命令。GPU、マルチプロセッサ、またはマルチコア コンピューターでは、"マルチスレッディング" を行って複数のスレッドを同時に実行できます。 |
プロセス | 1 つまたは複数のスレッドによるコンピューター プログラムのインスタンスの実行。プロセスごとに固有のメモリ ブロックがあります。 |
ノード | 1 つ以上の CPU または GPU を含むスタンドアロン コンピューター。ノードをネットワーク化してクラスターまたはスーパーコンピューターを形成できます。 |
クラスター | 複雑でデータ量の多いタスクを処理するために、統合システムとして連携して高性能の計算能力を提供する相互接続されたコンピューターの集合。 |
スケーラビリティ | リソースの追加による並列実行速度の上昇。 |
前提条件
このページの例を実行するには、Parallel Computing Toolbox™ ライセンスが必要です。Parallel Computing Toolbox がインストールされているかどうかを調べ、既定の並列プールをマシンで作成できるかどうかを確認するには、MATLAB® コマンド ウィンドウで次のコードを入力します。
if canUseParallelPool disp("Parallel Computing Toolbox is installed") else disp("Parallel Computing Toolbox is not installed") end
あるいは、インストールされている MathWorks® 製品を確認するには、コマンド ウィンドウで ver
を入力します。
MATLAB コードの高速化
コードを並列化する前に、ベクトル化や事前割り当てなどの手法を使用して MATLAB コードの逐次実行のパフォーマンスを高めることができます。多くの場合、逐次実行の高速化と並列化の組み合わせにより、累積的なパフォーマンスの向上が得られます。
ベクトル化
MATLAB は、行列とベクトルに関する演算に最適化されています。ループベースでスカラー指向のコードを、MATLAB 行列およびベクトル演算を使用するように変更するプロセスはベクトル化と呼ばれます。多くの場合、ループベースの演算の代わりにベクトル化コードを使用するとコードのパフォーマンスが向上します。
次のコードの抜粋は、ソフトウェアで 1,000,000 個の値の平方根を計算するために必要な時間について、ループベースのコードを使用する場合とベクトル化コードを使用する場合を比較したものです。
ベクトル化なし | ベクトル化あり |
---|---|
tic for k = 1:1000000 x(k) = sqrt(k); end toc Elapsed time is 0.112298 seconds. | tic k = 1:1000000; x = sqrt(k); toc Elapsed time is 0.006783 seconds. |
事前割り当て
ループを繰り返すたびに配列のサイズが段階的に増える while
ループと for
ループは、場合によってはパフォーマンスやメモリ使用量に悪影響を及ぼすことがあります。ループベースのコードを実行するときに、配列のサイズを継続的に変更する代わりに、配列に必要なスペースの最大容量を事前に割り当てることができます。
次のコードの抜粋は、ソフトウェアでスカラー変数 x
を作成するために必要な時間について、x
のサイズを for
ループで徐々に増やす場合と x
に 1 行 1,000,000 列のメモリ ブロックを事前に割り当てる場合を比較したものです。
事前割り当てなし | 事前割り当てあり |
---|---|
tic x = 0; for k = 2:1000000 x(k) = x(k-1) + 5; end toc Elapsed time is 0.103415 seconds. | tic x = zeros(1,1000000); for k = 2:1000000 x(k) = x(k-1) + 5; end toc Elapsed time is 0.018758 seconds. |
次の表に、初期化する配列のタイプに応じた適切な事前割り当て関数を示します。
初期化する配列タイプ | 事前割り当て関数 |
---|---|
数値 | zeros |
string | strings |
cell | cell |
table | table |
マルチコアおよびマルチプロセッサのノードでの MATLAB の実行
MATLAB では、マルチコアおよびマルチプロセッサのノードでコードを並列化する方法を 2 つサポートしています。
組み込みのマルチスレッディングによる暗黙的な並列化
一部の MATLAB 関数は、暗黙的にマルチスレッディングを使用して実行が並列化されます。これらの関数は、自動的に単一の MATLAB セッションで複数の計算スレッドに対して実行されるため、マルチコア対応マシンで実行すると高速になります。この例としては、fft
、mldivide
、eig
、svd
、sort
などの線形代数関数や数値関数があります。したがって、これらの関数を複数のコアがあるマシンで使用するとパフォーマンスの向上が見られます。
MATLAB ワーカーによる明示的な並列化
MATLAB および Parallel Computing Toolbox ソフトウェアでは、MATLAB ワーカーを使用してコードを明示的に並列化します。MATLAB ワーカーは、グラフィカル デスクトップなしでバックグラウンドで実行される MATLAB 計算エンジンです。操作する MATLAB セッションは MATLAB クライアントとも呼ばれ、このクライアントから並列言語関数を使用してワーカーに指示します。Parallel Computing Toolbox の関数を使用すると、タスクが自動的に分割され、そのタスクがこれらのワーカーに割り当てられて、計算が並列実行されます。
明示的な並列化のための環境の設定
Parallel Computing Toolbox がマシンにインストールされている場合、ワーカーの対話型並列プールを起動してマルチコア コンピューターのコアを利用できます。
並列プール ("parpool"
) は、コードを対話的に実行できる MATLAB ワーカーのグループです。
ワーカーの並列プールは、parpool
または自動並列サポートがある関数を使用して作成できます。既定では、並列プールが必要な場合、parfor
、parfeval
、spmd
などの並列言語関数で自動的に作成されます。ワーカーが起動すると、それらに MATLAB セッションが接続されます。たとえば、次のコードでは、並列プールが自動的に起動され、parfor
ループのステートメントが 6 つのワーカーで並列実行されます。
parfor i = 1:100 c(i) = max(eig(rand(1000))); end
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to parallel pool with 6 workers.
MATLAB デスクトップの左下隅にある並列ステータス インジケーターを使用して、並列プールを手動で起動することもできます。インジケーター アイコンをクリックし、[並列プールの起動] を選択します。
起動中の並列プールを停止するには、Ctrl+C または Ctrl+Break を押します。Apple macOS オペレーティング システムでは、command+ ("command" キーとプラス キー) も使用できます。
並列プールの起動には時間がかかることが多く、実行に数秒しかかからないコードではパフォーマンスに影響が生じる可能性があります。このオーバーヘッドの影響は、実行時間が長いコードほど少なくなります。
並列プール クラスターは既定の並列環境によって決まります。ローカル マシンの既定の並列環境の名前は Processes
です。この環境では、プロセス ワーカーの並列プールが起動されます。使用可能な並列環境の選択は、MATLAB の [ホーム] タブの [並列] メニューで確認できます。
メモ
既定の Processes
プロファイルでは、シングルの計算スレッドを使用する物理 CPU コアごとの既定のプロセス ワーカー数は 1 つです。この制限により、各ワーカーが浮動小数点演算装置に排他的にアクセスすることになり、通常は計算コードのパフォーマンスが最適化されます。コードの計算量が多くない場合、たとえば入出力 (I/O) が多いコードの場合は、物理コアごとに最大 2 つのワーカーを使用することを検討してください。少なすぎるリソースで多すぎるワーカーを実行すると、マシンのパフォーマンスと安定性に影響が生じることがあります。
次の表は、対話型並列プールを作成できるさまざまな方法をまとめたものです。
並列環境 | ワーカー タイプ | 位置 | 使用可能なコアまたはスレッドの数 |
---|---|---|---|
Processes | プロセス | ローカル マシン | 最大 512 コア |
Threads | スレッド | ローカル マシン | 最大 512 スレッド |
backgroundPool | スレッド | ローカル マシン | Parallel Computing Toolbox ライセンスなし: 1 スレッド |
Parallel Computing Toolbox ライセンスあり: | |||
Cluster | プロセス | オンサイトまたはクラウドのクラスター | クラスターで起動できるワーカーの最大数まで |
Parallel Computing Toolbox では、プロセス ワーカーの代わりに計算スレッドでサポートされる、ワーカーの並列プールの実行もサポートされます。この並列環境は Threads
と呼ばれます。スレッド ワーカーでは、メモリ使用量が削減され、スケジューリングが高速化され、データ転送コストが低減されます。ただし、スレッド ワーカーでは、プロセス ワーカーで使用できる MATLAB 関数のサブセットのみがサポートされます。
MATLAB では、backgroundPool
という追加のローカル並列環境もサポートされます。backgroundPool
環境はスレッド ワーカーをベースとしており、セッションで他のコードを実行しながら、同時にバックグラウンドでコードを実行できます。Parallel Computing Toolbox ライセンスがない場合、backgroundPool
環境で使用できるスレッド ワーカーは 1 つです。Parallel Computing Toolbox ライセンスがある場合、backgroundPool
のスレッド ワーカーの最大数は maxNumCompThreads
関数から返される値になります。
オンサイトまたはクラウドのクラスターにアクセスできる場合、[並列] 、 [クラスターの検出] をクリックしてプロンプトに従うことで、ネットワークまたは Cloud Center で実行されている他のクラスターを検出できます。クラスターの並列プールはプロセス ワーカーをベースとしており、並列言語を完全にサポートします。
ワーカーの対話型並列プールがある場合、並列言語関数を使用して大規模な問題を小さなタスクに分割し、ワーカーが並列実行するようにできます。MATLAB コードを高速化するには、parfor
などの対話型の並列機能を使用します。
parfor
ループを使用した明示的な並列化の実行
この例では、for
ループを parfor
ループに変換し、ワーカー数による parfor
ループのスケーラビリティを計算する方法を示します。
for
ループは、parfor
ループを使用することで、並列実行するように変換できます。多くの場合、for
は parfor
に単純に置き換えることができます。ただし、並列実行するためには、コードの調整がさらに必要になることが多くあります。
parfor
ループの仕組み
parfor
ループを実行する際、MATLAB はループ本体のステートメントを並列で実行します。parfor
ループの本体の各実行は "反復" です。MATLAB クライアントは parfor
コマンドを発行し、ワーカーと連係して並列プール内のワーカー上でループ反復を実行します。複数のワーカーで反復を同時に計算できるため、parfor
ループは類似の for
ループよりもはるかにパフォーマンスが高くなります。
parfor
ループを実行すると、MATLAB クライアントはループの反復をサブレンジに分割し、それらをワーカーに割り当てます。ワーカー数がループ反復数と同じである場合、各ワーカーはループの 1 つの反復を実行します。反復数がワーカー数よりも多い場合は、一部のワーカーが複数のループ反復を実行します。この場合、通信時間を短縮するために、ワーカーは一度に複数の反復を受け取ります。さらに、クライアントが parfor
ループ コードの静的解析を実行して、各ワーカーに転送するデータとクライアントに送り返すデータを判別します。クライアントは必要なデータをワーカーに送信し、ワーカーで計算の大部分が実行されます。その後、ワーカーがクライアントに結果を送り返し、それらの結果がクライアントでまとめられます。MATLAB ワーカーは特定の順序を定めず、相互に無関係なものとして反復を評価します。反復はそれぞれ独立しているため、反復を同期する必要はなく、多くの場合は同期されません。
parfor
ループは次の基本的な要件を満たす必要があります。
ループ反復が独立している。
for
ループをparfor
ループに変換するときは、ループ反復が独立していることを確認する必要があります。parfor
コードのループ反復間に依存関係がある場合、MATLAB エディターのコード アナライザーで依存関係が検出されます。このparfor
ループを実行するとエラーが生成されます。
ループ実行の順序が決まっていない。
parfor
ループの反復には確定的な順序はないため、parfor
ループを使用するコードがparfor
ループの出力の順序に依存しないことを確認する必要があります。
for
ループから parfor
ループへの変換
200 行 200 列の 5000 個の乱数行列における特異値分解の最大値を計算するコードで、for
を parfor
に置き換えて for
ループを parfor
ループに変換します。その parfor
ループを 6 つのワーカーで実行します。それらの実行時間を比較します。
parfor
を使用するとき、Parallel Computing Toolbox ソフトウェアがインストールされていれば、MATLAB で自動的にワーカーの並列プールが起動されます。並列プールの起動には時間がかかることがあります。この例は、プールが既に起動した状態での 2 回目の実行を示します。for
ループ コードよりも、6 つのワーカーで実行される parfor
コードの方がはるかに高速に実行されることがわかります。.
tic y = zeros(5000,1); for n = 1:5000 y(n) = max(svd(randn(200))); end toc
Elapsed time is 21.837346 seconds.
tic y = zeros(5000,1); parfor n = 1:5000 y(n) = max(svd(randn(200))); end toc
Elapsed time is 3.908282 seconds.
想定されるほどの高速化が得られない場合は、parfor
ループ コードのスケーラビリティを計算できます。
スケーラビリティの計算
この for
ループを parfor
ループに変換する場合のスケーラビリティを計算できます。スケーラビリティを使用して、parfor
ループ コードがワーカー数に応じて良好にスケーリングされるかどうか、および制限が存在するかどうかを調べます。
for
ループを使用して異なる数のワーカーを反復処理することで parfor
ループを実行します。ワーカー数を指定するには、parfor
の 2 番目の入力引数を使用します。使用可能なリソースに合わせて NumWorkers
配列の値を変更できます。
numIterations = 5000; numWorkers = [1 2 3 4 5 6]; t = zeros(size(numWorkers)); for w = 1:numel(numWorkers) tic; y = zeros(numIterations,1); parfor (n = 1:numIterations,numWorkers(w)) y(n) = max(svd(randn(200))); end t(w) = toc; end
1 つのワーカーでの計算時間と各最大ワーカー数での計算時間との比を計算して、高速化を計算します。タスクの並列化の効率を計算するには、実際に得られた高速化で理想的な高速化を除算します。
speedup = t(1)./t; efficiency = (speedup./numWorkers).*100;
ワーカー数と共に計算がスケールアップしている様子を可視化するには、この例の最後で定義している comparePlot
関数を使用して、高速化と効率をワーカー数に対してプロットします。
ワーカー数の増加と共に高速化が向上します。ワーカーを追加するほど計算時間は短くなりますが、ワーカー数が増えると効率が低下するため、スケーリングが完璧なわけではありません。これは並列化に伴うオーバーヘッドによるものです。並列オーバーヘッドには、ソフトウェアが必要とするクライアントとワーカーの間での通信、調整、データ転送の時間が含まれます。
一般に、反復や計算負荷の高いタスクがそれほど多くない parfor
ループは、ワーカー数を増やしても良好にスケーリングされません。ソフトウェアが計算に必要な時間と比較して、データ転送に必要な時間がかなりの長さになるためです。
comparePlot(numWorkers,speedup,efficiency);
計算が完了したら、現在の並列プールを削除できます。現在の並列プールはgcp
関数で取得します。
delete(gcp)
Parallel pool using the 'Processes' profile is shutting down.
補助関数
この関数は parfor
ループの高速化と効率をワーカー数に対してプロットします。
function comparePlot(numWorkers,speedup,efficiency) yyaxis left plot(numWorkers,speedup,'-*') grid on title('Speedup and Efficiency with Number of Workers'); xlabel('Number of Workers'); xticks(numWorkers); ylabel('Speedup'); yyaxis right plot(numWorkers,efficiency,'--o'); ylabel('Efficiency') xticks(numWorkers); ylabel('Efficiency (%)'); legend('Speedup','Efficiency') end
その他の並列言語関数の確認
Parallel Computing Toolbox で他の並列言語関数を使用して以下のタスクを実行できます。
parfeval
を使用して非同期処理を実行する。gpuArray
を使用してコンピューターのサポートされている GPU で計算を高速化する。distributed
やtall
などのビッグ データ処理ツールを並列プールで使用して計算をスケールアップする。batch
を使用して計算をコンピューター クラスターまたはクラウド コンピューティング機能にオフロードする。parsim
(Simulink) およびbatchsim
(Simulink) を使用して Simulink® モデルを並列実行する。MATLAB Parallel Server™ ソフトウェアを使用して計算をオンサイトまたはクラウドのクラスターにオフロードする。詳細については、クラスターとクラウドを参照してください。
いくつかの MathWorks 製品では、追加のコーディングを行わずに並列計算製品の組み込みサポートが提供されるようになりました。このような製品の最新リストおよびその並列機能については、Parallel Computing Support in MATLAB and Simulink Products を参照してください。
並列言語関数とその用途の詳細については、並列計算の解決策の選択および並列言語の意思決定表を参照してください。
参考
for
| parfor
| parfeval
| gpuArray
| distributed
| tall
| datastore
| mapreduce
| batch
| parsim
(Simulink) | batchsim
(Simulink)