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

概要

本書は、下記のホワイトペーパーシリーズの一部です:
「マルチコアプログラミングの基礎」ホワイトペーパーシリーズ



「マルチコアプログラミングの基礎」ホワイトペーパーシリーズ

マルチスレッドプログラミングは、マルチコアプロセッサを活用する上で非常に重要です。アプリケーションを複数のスレッドに分割することで、オペレーティングシステムはこれらのスレッドをPCの複数の処理コアに分散またはスケジュールできます。本書では、NIのLabVIEWにおけるマルチスレッドセーフおよび再入可能の関数とドライバを使用することで得られる、マルチコアプロセッサに関する利点について説明します。

内容

並列 vs.マルチレッドセーフ動作

従来の言語では、並列実行のためにはプログラムを別々のスレッドに分割する必要があります。分割された各スレッドは同時に実行することができます。マルチスレッドアプリケーションで安全に実行できるコードの作成と、マルチコアシステムで最大限の性能を実現できる並列実行用コードの作成には違いがあります。プログラム作成時に使用するドライバや関数で、この違いがよく見られます。マルチスレッドセーフ関数は複数のスレッドから呼び出すことができ、データを上書きしないため、実行をブロックして競合を防ぎます。1つのスレッドが関数を呼び出している場合、その関数を呼び出そうとしている他のスレッドは、最初のスレッドが終わるまで待機します。再入可能関数の場合は、複数のスレッドが同じ関数を同時に並列で呼び出し、実行することが可能です。これらのサンプルはマルチスレッドプログラムで正しく実行しますが、再入可能関数は同時実行するためさらに高速での実行が可能です。

メモリ vs LabVIEWにおけるパフォーマンストレードオフ

LabVIEWでは、ワイヤを流れるデータは、通常そのデータに対して実行される関数には依存しません。本質的にワイヤ上のデータは、そのワイヤに接続されていないVI/関数が簡単にアクセスすることはできません。LabVIEWは、ワイヤを分割したとき必要に応じてデータのコピーを作成しますので、以降のVIは独立した別々のバージョンのデータに対して操作できます。ほとんどのLabVIEW VIおよびドライバは、マルチスレッドセーフかつ再入可能です。ただし、一部のLabVIEW内蔵ライブラリVIのデフォルト構成を再入不可能に設定することができます。再入可能VIはより多くのメモリを使用するため、メモリ使用率と並列性の間でのトレードオフが必要となることもあります。多くの場合、LabVIEWはデフォルトでメモリ節約や再入不可能設定を選択し、最大限の並列処理を目指すかどうかはユーザーに委ねます。その場合、ライブラリVIは簡単に再入可能に設定できます。

再入可能関数

関数へのアクセスに問題が生じるのを防ぐために、再入不可能関数やプログラムを使用する必要がある場合や環境があります。マルチスレッドセーフライブラリの多くは、リソースのロック、すなわち1つのスレッドがある関数を呼び出すと、その関数またはライブラリ全体を他のスレッドから呼び出されないようロックすることで、スレッドセーフを実現します。並列処理の状況で、コードの2つの異なるパスまたはスレッドが同じライブラリや関数を呼び出そうとする場合、ロックが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プロパティを選択し、ドロップダウンメニューから実行を選択します。 

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

大量のクローンVIを事前に割り当てる際にメモリ使用率を低減させるには、共有クローン再入実行オプションを選択します。共有クローン再入実行オプションを選択すると、LabVIEWは再入可能VIが呼び出されるまでクローンVIを作成しません。このオプションを選択すると、LabVIEWは必要に応じてクローンVIを作成するため、VIの実行にジッタを引き起こす可能性があります。LabVIEWでは、再入可能VIへの呼び出し全体で状態の情報は確保されません。

 

LabVIEWドライバ機能

ハードウェアとの通信を行う場合は、スレッドセーフかつ再入可能なドライバを使用することが重要です。そのようなドライバを使うことで、マルチコア技術のメリットを引き出し、性能を高めることができます。

旧バージョンのLabVIEWでは、デバイスドライバに再入可能機能は必ずしも備わっていませんでした。例えば従来型NI-DAQは、2つのスレッドが同時に呼び出しても停止しないという点で、マルチスレッドセーフであると言えます。あるスレッドが任意のNI-DAQ関数を呼び出すと、他の全てのスレッドは、その関数が終了するまで待たなければNI-DAQ関数を実行することができないグローバルロックというテクニックが用いられています。

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

NIのモジュール式計測器ドライバも、NI-DAQmxと同様に機能します。表1のドライバはすべて、スレッドセーフであり再入可能です。いずれのドライバも、2つの異なるデバイス上で同じ関数を同時に呼び出すことができます。複数の計測器を使った大規模システムでは、特にメリットがあります。


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

結論

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

 NI-DAQmxNI-DMMNI-ScopeNI-RFSA/RFSGNI-HSDIONI-DCPower
スレッドセーフ      
再入可能      

Was this information helpful?

Yes

No