LabVIEW関数およびドライバマルチスレッド機能

概要

このドキュメントは、マルチコアプログラミングの基本シリーズの一部です。
マルチコアプログラミングの基本シリーズ

マルチコアプログラミングの基本シリーズ

マルチコアプロセッサの能力を最大限に活かすためには、マルチスレッドプログラミングが欠かせません。アプリケーションを複数のスレッドに分割すると、オペレーティングシステムはこれらのスレッドをコンピュータの複数のプロセッサコア間で適切に分配(スケジューリング)します。このドキュメントでは、NI LabVIEWでマルチコアプロセッサを使用したマルチスレッドセーフで再入可能な関数とドライバを使用することの利点について説明します。

内容

並列実行マルチレッドセーフ違い

従来のプログラミング言語では、並列実行を行うにはプログラムを複数のスレッドに分割する必要があります。分割された各スレッドは同時に実行することができます。ただし、マルチスレッドセーフアプリケーションで問題なく実行できるコードを記述することと、マルチコアシステムで最大のパフォーマンスを得るために並列実行するコードを記述することは、異なります。この違いは、プログラムの記述に使用するドライバや関数で表れます。マルチスレッドセーフ関数は、複数のスレッドからデータを上書きすることなく呼び出せるため、実行がブロックされて競合が発生することがありません。1つのスレッドが関数を呼び出すと、同じ関数の呼び出しを試みる他のスレッドは最初のスレッドが完了するまで待機しなければなりません。再入可能関数は、それに加えて、複数のスレッドから同時に呼び出して並列実行することができます。これらの例はどちらもマルチスレッドプログラムで正常に実行されますが、同時に実行される再入可能関数を使用したほうが高速です。

LabVIEWにおけるメモリパフォーマンスバランス

LabVIEWでは、一般的にワイヤ上のデータはデータを処理する関数とは独立しています。ワイヤ上のデータには、そのワイヤに接続されていないVIや関数から簡単にはアクセスできません。必要であれば、ワイヤを分岐することでデータのコピーを作成して、後続のVIで処理できます。また、多くのLabVIEW VIおよびドライバはマルチスレッドセーフであり再入実行が可能です。標準ライブラリVIの中には、デフォルトで再入不可能に設定できるものがあります。再入可能VIはメモリを多く占有するため、メモリ使用率と並列実行のバランスを考慮する必要があります。LabVIEWは、デフォルトでメモリをなるべく節約してVIを再入不可能に設定する傾向にあります。並列実行を最大限に生かす必要がある場合は、開発者が意図的に設定します。ライブラリVIは簡単に再入可能に設定できます。

再入可能関数

場合や環境によっては、関数へのアクセスエラーを防ぐために関数またはプログラムを再入不可能に設定しなければならないことがあります。マルチスレッドセーフライブラリの多くは、リソースのロック、すなわち1つのスレッドがある関数を呼び出すと、その関数またはライブラリ全体を他のスレッドから呼び出されないようロックすることで、スレッドセーフを実現します。並列実行では、2つのコードのパス(スレッド)が1つのライブラリや関数へ同時にアクセスしようとすると、一方のスレッドが完了するまで、もう1つのスレッドは強制的に待機状態にされるか、ブロックされます。一度に1つのスレッドだけが関数にアクセスできるようにすると、余分なインスタンスが必要なくなるためメモリスペースが節約されます。

前述の説明のとおり、並列プログラミング手法を再入可能関数と組み合わせることで、コードのパフォーマンスを向上させることができます。

LabVIEWのデバイスドライバ(NI-DAQmxなど)はマルチスレッドセーフかつ再入可能であるため、関数を複数のスレッドからブロックされることなく同時に呼び出して正常に動作させることができます。これは、並列コードを記述したりマルチコアシステムのパフォーマンスを最適化する上で重要な機能です。再入不可能なコードを使用すると、各関数にアクセスする際にその関数を使用中の他のスレッドが完了するまで待機する必要があるため、パフォーマンスが低くなる可能性があります。この状態は、LabVIEWのVI階層機能によってより明確に理解することができます。個々のVIの階層は、表示 » VI階層を選択して表示できます。図1のVI階層では、F1とF2は同じVI(非常に大量のデータを処理する高速フーリエ変換アルゴリズム)に依存しています。F1とF2を並列実行するためには、このVIは必ず再入可能でなければなりません。

図1. LabVIEWのVI階層

コード内の不要な依存性をなくすためには、再入可能かどうかを検討することが重要です。LabVIEWの解析VIは、デフォルトで再入可能なものもあれば再入不可能なものもあるため、これらのVIが確実に並列実行されるかどうかプロパティで確認することが重要です。

LabVIEW構成

LabVIEW VIを再入可能に設定するには、ファイル→VIプロパティを選択し、ドロップダウンメニューから実行を選択します。再入実行チェックボックスをオンにし、クローン方法を選択します。

図2. VIプロパティダイアログボックスの再入実行オプション

LabVIEWは、2種類の再入可能VIをサポートしています。再入可能VIの各呼び出しに対するクローンVIをあらかじめ作成する場合、またクローンVIがすべての呼び出しに対して状態情報を維持する必要がある場合は、各インスタンスのクローンを事前に割り当てるオプションを選択します。たとえば、再入可能VIに初期化されないシフトレジスタや、クローンVIの次回の呼び出しまで維持する必要がある値を含むローカル変数、プロパティ、メソッドが含まれる場合は、各インスタンスのクローンを事前に割り当てるオプションを選択します。また、再入可能VIに「初めて呼び出す?(First Call?)」関数が含まれる場合にも、このオプションを選択します。さらに、LabVIEW Real-Timeシステムで実行するVIにも、ジッタを最小限にするためにこのオプションを選択します。

多数のクローンVIをメモリに事前に割り当てることでメモリ使用率が増加しないようにするためには、インスタンス間でクローンを共有するオプションを選択します。このオプションを選択すると、再入可能VIが実際に呼び出されるまでクローンVIが作成されません。このオプションを有効にすると、クローンVIが必要時に作成されるため、VIの実行時にジッタが発生する可能性があります。また、再入可能VIのすべての呼び出しに対して状態の情報が維持されません。

LabVIEWドライバ機能

ハードウェアと通信する場合はハードウェアのタイプに関係なく、スレッドセーフかつ再入可能なドライバを使用する必要があります。これらの特性により、マルチコア技術の利点を生かしてパフォーマンスを向上させることができます。

LabVIEWの旧バージョンのデバイスドライバでは、すべての関数が再入可能というわけではありませんでした。たとえば、従来型NI-DAQはマルチスレッドセーフですが、2つのスレッドから同時に呼び出されてもエラーが発生しないという意味においてです。この機能は、グローバルロック、つまり1つのスレッドがあるNI-DAQ関数を呼び出したら、NI-DAQ関数を使用する他のスレッドはすべて最初の関数が完了するまで待機しなければならない仕組みによって実現していました。

一方、NI-DAQmxではより洗練された並列マルチスレッド環境が提供されています。NI-DAQmxは再入可能で、複数のスレッドが同時にドライバの関数を呼び出すことができます。2つのボードの異なるアナログ入力が、同じプログラム内の別々のスレッドからブロックされることなく同時に実行されます。また、2つの独立したスレッドのアナログ入力とデジタル入力を1つのボード上で同時に実行できます。このような洗練されたNI-DAQmxドライバの機能により、1つのハードウェアリソースを2つの異なるリソースとして扱うことができます。

NIモジュール式計測器ドライバも、NI-DAQmxと同様に機能します。表1のドライバはすべて、スレッドセーフであり再入可能です。したがって、1つの関数を異なるデバイスから同時に呼び出すことができます。この機能は、複数の計測器を使用する大規模システムのコードで非常に有効です。

表1. スレッドセーフおよび再入可能なモジュール式計測器ドライバ

まとめ

並列プログラミングによってマルチコアアーキテクチャの利点を生かす場合、プログラミング言語の種類や並列コードの記述についてだけでなく、ドライバや関数が並列環境に適しているかも考慮する必要があります。

Was this information helpful?

Yes

No