メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

MATLAB での並列計算の基本操作

並列計算を使用して多数の計算を同時に実行できます。大規模な問題を小規模な問題に分割し、それらを同時に処理できます。

並列計算を使用して次のことが可能です。

  • タスクを分散して同時実行することで時間を節約

  • データを分割してビッグ データの問題を解決

  • デスクトップ コンピューターのリソースを利用してクラスターおよびクラウド コンピューティングにスケール アップ

Diagram that shows four MATLAB workers in a loop.

次の表に、並列計算の基本的な用語とその定義の一部を示します。

用語定義
スレッド

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
stringstrings
cellcell
tabletable

マルチコアおよびマルチプロセッサのノードでの MATLAB の実行

MATLAB では、マルチコアおよびマルチプロセッサのノードでコードを並列化する方法を 2 つサポートしています。

組み込みのマルチスレッディングによる暗黙的な並列化

一部の MATLAB 関数は、暗黙的にマルチスレッディングを使用して実行が並列化されます。これらの関数は、自動的に単一の MATLAB セッションで複数の計算スレッドに対して実行されるため、マルチコア対応マシンで実行すると高速になります。この例としては、fftmldivideeigsvdsort などの線形代数関数や数値関数があります。したがって、これらの関数を複数のコアがあるマシンで使用するとパフォーマンスの向上が見られます。

Diagram comparing the time it takes a MATLAB client using multithreading to accelerate task execution to a MATLAB client that does not use panellization.

MATLAB ワーカーによる明示的な並列化

MATLAB および Parallel Computing Toolbox ソフトウェアでは、MATLAB ワーカーを使用してコードを明示的に並列化します。MATLAB ワーカーは、グラフィカル デスクトップなしでバックグラウンドで実行される MATLAB 計算エンジンです。操作する MATLAB セッションは MATLAB クライアントとも呼ばれ、このクライアントから並列言語関数を使用してワーカーに指示します。Parallel Computing Toolbox の関数を使用すると、タスクが自動的に分割され、そのタスクがこれらのワーカーに割り当てられて、計算が並列実行されます。

Diagram comparing the time it takes parallel computing workers to accelerate task execution to a MATLAB client with no parallelization.

明示的な並列化のための環境の設定

Parallel Computing Toolbox がマシンにインストールされている場合、ワーカーの対話型並列プールを起動してマルチコア コンピューターのコアを利用できます。

並列プール ("parpool") は、コードを対話的に実行できる MATLAB ワーカーのグループです。

ワーカーの並列プールは、parpool または自動並列サポートがある関数を使用して作成できます。既定では、並列プールが必要な場合、parforparfevalspmd などの並列言語関数で自動的に作成されます。ワーカーが起動すると、それらに 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 デスクトップの左下隅にある並列ステータス インジケーターを使用して、並列プールを手動で起動することもできます。インジケーター アイコンをクリックし、[並列プールの起動] を選択します。

The parallel status indicator, including a menu showing options for starting a parallel pool and inspecting your parallel settings.

起動中の並列プールを停止するには、Ctrl+C または Ctrl+Break を押します。Apple macOS オペレーティング システムでは、command+ ("command" キーとプラス キー) も使用できます。

並列プールの起動には時間がかかることが多く、実行に数秒しかかからないコードではパフォーマンスに影響が生じる可能性があります。このオーバーヘッドの影響は、実行時間が長いコードほど少なくなります。

並列プール クラスターは既定の並列環境によって決まります。ローカル マシンの既定の並列環境の名前は Processes です。この環境では、プロセス ワーカーの並列プールが起動されます。使用可能な並列環境の選択は、MATLAB の [ホーム] タブの [並列] メニューで確認できます。

Selection of the Processes local cluster profile from the MATLAB menu.

メモ

既定の Processes プロファイルでは、シングルの計算スレッドを使用する物理 CPU コアごとの既定のプロセス ワーカー数は 1 つです。この制限により、各ワーカーが浮動小数点演算装置に排他的にアクセスすることになり、通常は計算コードのパフォーマンスが最適化されます。コードの計算量が多くない場合、たとえば入出力 (I/O) が多いコードの場合は、物理コアごとに最大 2 つのワーカーを使用することを検討してください。少なすぎるリソースで多すぎるワーカーを実行すると、マシンのパフォーマンスと安定性に影響が生じることがあります。

次の表は、対話型並列プールを作成できるさまざまな方法をまとめたものです。

並列環境ワーカー タイプ位置使用可能なコアまたはスレッドの数
Processesプロセスローカル マシン

最大 512 コア

Threadsスレッドローカル マシン

最大 512 スレッド

backgroundPoolスレッドローカル マシン

Parallel Computing Toolbox ライセンスなし: 1 スレッド

Parallel Computing Toolbox ライセンスあり: maxNumCompThreads 関数から返されるスレッド数まで

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 ループを使用することで、並列実行するように変換できます。多くの場合、forparfor に単純に置き換えることができます。ただし、並列実行するためには、コードの調整がさらに必要になることが多くあります。

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 個の乱数行列における特異値分解の最大値を計算するコードで、forparfor に置き換えて 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 で計算を高速化する。

  • distributedtall などのビッグ データ処理ツールを並列プールで使用して計算をスケールアップする。

  • batch を使用して計算をコンピューター クラスターまたはクラウド コンピューティング機能にオフロードする。

  • parsim (Simulink) および batchsim (Simulink) を使用して Simulink® モデルを並列実行する。

  • MATLAB Parallel Server™ ソフトウェアを使用して計算をオンサイトまたはクラウドのクラスターにオフロードする。詳細については、クラスターとクラウドを参照してください。

いくつかの MathWorks 製品では、追加のコーディングを行わずに並列計算製品の組み込みサポートが提供されるようになりました。このような製品の最新リストおよびその並列機能については、Parallel Computing Support in MATLAB and Simulink Products を参照してください。

並列言語関数とその用途の詳細については、並列計算の解決策の選択および並列言語の意思決定表を参照してください。

参考

| | | | | | | | | (Simulink) | (Simulink)

トピック