Teighaマルチスレッド高レベルAPI(3部構成のパート3)

この記事は、マルチスレッドに使用されるスレッドプールサービスインターフェースに関する一連の記事の一部です。前の記事については、パート1パート2を参照してください。

パフォーマンスの測定

パフォーマンス測定のために、Teigha Kernelパフォーマンスタイマーを含めます。

#include "OdPerfTimer.h"

And construct it in our main application function:
// Init performance timer
OdPerfTimerWrapper perfTimer;

ここでは、OdPerfTimerWrapperパフォーマンスタイマーラッパーを使用しました。ラッパーを使用すると、OdPerfTimerWrapperクラスのコンストラクタでパフォーマンスタイマーが自動的に構築され、メイン実行可能関数の最後にOdPerfTimerWrapperクラスのデストラクタで破棄されるため、コードが簡素化されます。

これで、OdPerfTimerBaseのstartおよびstopメソッドを使用して、パフォーマンス測定が必要なソースコードの部分をラップできます。

// Start timing for "render database to image" process
perfTimer.getTimer()->start();

// Run loading and rendering process
for (OdUInt32 nInput = 0; nInput < generatedRasters.size(); nInput++)
{
  OdString inputFileName(argv[2 + nInput]);
  pMTQueue->addEntryPoint(OdRxObjectImpl<RenderDbToImageCaller>::createObject()->setup(inputFileName, &generatedRasters[nInput]), (OdApcParamType)&renderDbContext);
}

// Wait for threads completion
pMTQueue->wait();
pMTQueue.release();

// Output timing for "render database to image" process
perfTimer.getTimer()->stop();
odPrintConsoleString(L"%u files loaded and rendered in %f seconds\n", generatedRasters.size(), perfTimer.getTimer()->countedSec());

startおよびstopメソッドのスコープには、スレッドの実行とスレッドの実行結果の待機が含まれます。最後に、測定結果を秒単位で出力します。同様に、OdPerfTimerBaseのstartおよびstopメソッドのスコープを配置して、ラスター画像処理のパフォーマンスを測定します。測定結果は次のようになります。

4つのファイルが0.509886秒でロードおよびレンダリングされました

最終ラスター画像は0.542890秒で処理されました

これはマルチスレッドが有効な場合の結果ですが、真の最適化を達成したことを確認するために、シングルスレッドソリューションと比較する必要があります。このタスクでは、マルチスレッドキューの使用をシングルスレッドキューに単純に変更できます。

// OdApcQueuePtr pMTQueue = pThreadPool->newMTQueue(ThreadsCounter::kMtLoadingAttributes | ThreadsCounter::kMtRegenAttributes);
OdApcQueuePtr pMTQueue = pThreadPool->newSTQueue();

OdRxThreadPoolService::newSTQueueメソッドは、OdRxThreadPoolService::newMTQueueメソッドと同様のOdApcQueueインターフェースを返すため、パフォーマンス測定のためにコードの他の部分を変更する必要はありません。OdApcQueue::addEntryPointおよびOdApcQueue::waitメソッドは以前と同様に呼び出すことができます。マルチスレッドキューとの違いは、シングルスレッドキューが要求されたすべてのタスクを1つの専用スレッドで実行することです。

さまざまなパフォーマンス測定結果を確認できます。

4つのファイルが1.081148秒でロードおよびレンダリングされました

最終的なラスター画像は1.824529秒で処理されました

マルチスレッドを有効にすると、ライブラリ構成と環境データベースのロードおよびレンダリングプロセスが約2倍高速になります。ラスター画像処理は、マルチスレッドを有効にすると約3倍高速になります。この違いは、ラスター画像処理が、データベースのロードやベクトル化プロセスと比較して、スレッド間の共有リソースとメモリアクセスに対する同期を必要としないためです。

結論

スレッドプールサービスAPIを使用すると、マルチスレッドソリューションの実装を大幅に簡素化できます。このAPIには、スレッドとキューを操作するためのインターフェースだけでなく、マルチスレッド同期のためのインターフェースセットも含まれています。

たとえば、OdApcEventインターフェースのようなクロスプラットフォームで実装された古典的なイベントオブジェクトを考えてみましょう。OdApcEventは、単純なマルチスレッド同期タスクに使用できます。共有リソースアクセスに役立ちます。たとえば、最初のスレッドは、マルチスレッドアクセス中に競合を引き起こす可能性のあるコードの一部に入る前にOdApcEvent::resetメソッドを呼び出し、このコードの一部を離れた後にOdApcEvent::setメソッドを呼び出します。2番目のスレッドは、OdApcEvent::waitメソッドを使用して、最初のスレッドがOdApcEvent::setメソッドを呼び出すまで待機し、その後、マルチスレッドアクセス中に競合を引き起こす可能性のあるコードの一部に入り、最初のスレッド処理の結果を使用できます。待機中のスレッドはCPUリソースを使用しないため、これは複数のスレッドの同期に対する通常のソリューションです。スレッド同期オブジェクトを使用することで、複数のスレッドがクリティカルなコードセクションで安定して動作し、マルチスレッド処理の結果が破損しないことが保証されます。

スレッドプールサービスAPIには、より複雑な同期オブジェクトであるOdApcGatewayとOdApcLoopedGatewayも含まれています。しかし、それらの説明はこの記事の範囲を超えています。

今後のブログ記事では、Teighaのマルチスレッド機能に関するこの議論を続けます。低レベルのTeigha KernelマルチスレッドAPIと、それが高レベルのスレッドプールサービスAPIとどのように通信するかについて説明します。

今すぐ始める

ODAソフトウェアを60日間無料でお試しください。
リスクなし、クレジットカード不要。

無料で試す