並列プログラミングでのスレッドプーリングの概要

提供: Support
移動先: 案内検索

概要

Delphiが提供しているランタイムライブラリ(RTL)の1つとして「並列プログラミングライブラリ」があります。


並列プログラミングライブラリを使用することで、アプリケーションはタスクを並列に動作させ、複数のCPUデバイスやコンピュータでの分散処理を活用することができます。

この機能を活用することによって、従来のコーディングで非常に時間がかかっていた処理時間を大幅に短縮し、パフォーマンスの向上が見込めます。


その代表的な例としてforループなどの従来の処理をTParallel.Forへの置き換えがあります。

詳しくは、「チュートリアル:並列プログラミング ライブラリの for ループを使用する」を参照してください。


並列プログラミングライブラリでは、CPUの負荷に応じて自動的にワーカースレッドが作成されます。 ワーカースレッドを管理しているのがSystem.Threading.TThreadPool というクラスです。


現在、docwikiの記事にはTThreadPoolに関する情報が少ないため、こちらのサポート記事で補足させていただきます。


解説

TThreadPoolクラスは、並列プログラミングライブラリ(例えば、TParallel)で使用するワーカースレッドを管理しています。 作成されたワーカースレッド数は、TThreadPool.MaxWorkerThreadsプロパティで取得できます。


TThreadPoolのワーカースレッド数を取得するコード例は、以下の通りです。


Delphi:

uses System.Threading;
..
..
var
  psize : integer;
begin
  psize := TThreadPool.Default.MaxWorkerThreads;
  ShowMessage('Pool size = '+IntToStr(psize));
end;

C++Builder:

#include <System.Threading.hpp>
...
...
int psize = TThreadPool::Default->MaxWorkerThreads;
ShowMessage("Pool size=" + IntToStr(psize));


MaxWorkerThreadで取得できる値は、CPUコアの数とコアごとの最大スレッド数から算出されます。 もう少し具体的に説明すると、クラス内部では、以下のように定義されています。

MaxThreadsPerCPU = 25;  
..
..
FMaxLimitWorkerThreadCount := TThread.ProcessorCount * MaxThreadsPerCPU;
..
..
function TThreadPool.GetMaxWorkerThreads: Integer;
begin
  Result := FMaxLimitWorkerThreadCount;
end;
..
..

つまり、MaxWorkerThreadは、ProcessorCount × MaxThreadsPerCPU(=25)で算出されます。

TThread.ProcessorCountは、実行しているPCのコア数に依存しています。


例えば、実行しているPCのMaxWorkerThreadの値は、

  • コア数=2の場合、2×25=50
  • コア数=4の場合、4×25=100
  • コア数=8の場合、8×25=200

となり、並列プログラミングライブラリでは、コア数が多いほど、ワーカースレッド数の上限値は多く設定され、その範囲内でスレッドをプーリングします。


ただし、闇雲にワーカースレッド数を増やせば良いというわけではありません。

もし実行環境のPCのスペックを見ないで、固定でワーカースレッド数を設定してしまうと、CPU使用率を過度に圧迫してしまい、逆にパフォーマンスの低下を招く恐れがあります。


よって、通常の場合、開発者がスレッドプーリング数を変更する必要はなく、ThreadPoolのデフォルトの設定で使用することをお勧めします。

関連情報