【LabVIEW】ストラクチャ関数についての解説

2022年5月17日

本記事はLabVIEWのストラクチャ関数について解説を行っています。LabVIEWのストラクチャ関数にはWhileループやForループなどが含まれています。

本記事について

まだFor、Whileループについてしか記載されていません

ストラクチャについて

ストラクチャ関数の中にはループ処理でよく出てくる、ForループやWhileループといった関数が含まれています。

他にもC言語などのIf文に相当するケースストラクチャなどLabVIEW独自の構造体に関するコマンドがストラクチャの中に入っています。

Forループ

ある決まった回数または条件でループしたい場合、または配列の数で何らかの処理を行いたい場合に使用するループです。

無限ループの場合は後述するWhileループを通常は使用します。

Forループの基本的な使い方

Forループの基本的な使い方としては左上の『N』にループさせたい回数を「I32」数値で入力を行います。

上図の場合だと、Forループ内にあるプログラムを10回実行します。

Forループを設置したときに『N』と同時に設置されている『i』はループの反復回数を表しておりが何回ループが実行されたかを出力します。

注意点としては、初回のループは『ゼロ』が出力されるため、ループが10回実行されたときに『i』から出力される値は『9』になります。

もし、ループの回数と表示を一致させたいのであれば、インクリメント関数を追加することで、ループの回数と表示を一致させることが出来ます。

※プログラムの実行速度から見ると無駄な処理を行っているので、実行速度を優先する場合は出来るだけ追加しないことが望ましい。

Forループへデータを入力する

Forループの外からデータを入力する場合は、Forループの枠を選択するか、Forループの中にある関数を選択することで入力をすることが出来ます。

または、Forループ内の何もない場所でダブルクリックしても枠を選択したときと同じ入力状態になります。

何もない場所でシングルクリックを押した後にダブルクリックをするとForループ内にシングルクリックした場所まで不良ワイヤが発生します。

Forループの枠に入力データに応じたアイコンが出ているので、そこから内部の関数へワイヤーを接続します。※ループへ入力するデータは基本的に左から入力して右へ出力をするようにしてください。

Forループへ配列データを入力する

Forループに配列データを入力するとデフォルトでは自動で指標付けという処理がされるため、指標0から、順に要素が取り出されます。

上図の場合だと、要素の値は0,1…5の順で要素がループごとに出てきます。

また、自動で指標付けの配列が入力されている場合、配列サイズがループ回数となり、左上にある『N』にループの回数を入力する必要はありません。

上図は配列サイズが『5』なのでループの回数は5回になります。

Forループ入力側の指標付けを変更する場合

配列データを要素単位ではなく、そのままForループへ入力を行いたい場合はForループに入力している配列データの端子にカーソルがワイヤーの状態で合わせて(端子が点滅)から右クリックでメニューを表示します。

指標付不使用を選択すると配列データをForループ内に入力することができます。

注意、指標付けが無くなるので、左上のNにループを入力しないと実行エラーになります。

Forループへ二次元配列を入力する

Forループへ2D配列のデータを直接入れたい場合は、1D配列と同様に自動で指標付けを止めることで配列をForループ内へ入力することが出来ます。

2D配列の場合に自動で指標付けを行うと一つ目のForループへ入力した場合、1D配列が出力されるようになります。

0行目、1行目、2行目…n行目の順番で出力され、行の数だけループが行われます。

更に二つ目のForループでも自動で指標付けを行うと要素単位での出力になります。

2D配列を3重のForループで囲んでも要素データよりも分解は出来ないので、3重目も2重目と同様に要素データがループ内に入力されます。

配列が3D配列データであれば、3重目でようやく要素データとなります。

Forループからの出力データを配列データにする

Forループ内から外にワイヤーを引っ張ると自動で『指標付け』という処理が行われ配列データとして出力がされます。

上図の場合、ループが10回実行すると『i』から順番に『0,1,2,3….9』と値が順番に出力されます。

この『i』から出力された値を配列データの指標『0』から順に入力していき、Forループが終了した場合に、配列データとして出力します。

Forループでの配列作成例

あるプログラムを組んでいるときに入力された値で設定した条件で想定通りの動作をするのかを確認するために、Forループ内に乱数を入れて、1D配列の数値データを作成したりする場合があります。

Forループで2次元以上の配列データを作成する場合

Forループの外に更にForループを重ねることで、出力される値を2D配列として出力をすることが出来ます。

この場合は、外側のForループが1回実行されるごとに内部のForループが10回実行されるので合計100回の処理が実行されていることになります。

Forループを3重にすることで、3Dの配列データを作成することも可能です。

Forループ出力側の指標付けを変更する場合

Forループから出力されている、四角いマークの所にカーソルがワイヤーの状態で重ねると点滅を開始するので右クリックをするとメニューが表示されます。

メニュー内にトンネルモードという項目があるので、最後の値を選択すると最終のループで出力されている値のみを出すことが出来ます。

元の指標付けされた配列データで出力を行いたい場合は、指標を再度選択することで元に戻すことが出来ます。

あと、『連結』という項目がありますが、NIとしても配列データを作るためにはあまりオススメされていない機能です。

出力された値を繋げて配列データを作成することが出来ますが、特に大きな配列データを取り扱う場合に使用するとメモリが上限に達する原因となるため、通常は指標付けを使用します。

『トンネルモード』を最後の値に設定すると上図の様に、最終ループの値のみが出力されます。

前のループの値を次のループへ引き渡す(シフトレジスタ)

シフトレジスタという機能を用いることで、前のループで計算した値等を次のループでも使用することが出来ます。

例として数値データを用いていますが、ブール、文字列、バリアントデータなど特にデータタイプの指定はありません。

また、要素データだけではなく配列データもシフトレジスタを用いてデータを引き渡すことも可能です。

シフトレジスタを使用するには、

①Forループに入力または出力の端子を作成します。

②カーソルをワイヤーの状態に変更をして、端子にカーソルを重ねてから右クリックでメニューを表示

③メニューの中に『シフトレジスタと置換』という項目があるので選択をします。

④カーソルがシフトレジスタのアイコンに切り替わるので、置換されていないトンネル端子を選択してシフトレジスタに置換をします。

※端子を選択せずにいずれかの場所をクリックした場合はシフトレジスタの端子が新規作成されます。

※出力端子が一つも無い場合はシフトレジスタ端子は自動的に作成されます。

シフトレジスタの値について

反復回数「0」初めてのループの場合は、Forループの外から入力された値が初期値になります。

反復回数「1」以降は出力側のシフトレジスタへ入力された値が、次回の入力のシフトレジスタから出てきます。

Forループが終了した場合にForループから出力される値はトンネルモードの「最後の値」と同じく、シフトレジスタへ最後に入力された値となります。

入力側のシフトレジスタを増やす

入力側に限り、シフトレジスタの数を増やすことが出来ます。

通常は前のループの値だけを参照することが出来ますが、シフトレジスタの数を増やすことで、複数前のループの値を参照することが出来るようになります。

例では3つ前のループの値を参照するところまで出していますが、さらにシフトレジスタを増やして前の値まで参照することが出来ます。

シフトレジスタを使用したプログラム例

①初期化配列を使用して、任意の配列を作成します。

②配列サイズなどでForループへループ回数を入力します。

③初期化配列をシフトレジスタへ入力をします。

④部分配列置換で配列の値を置き換えます。(指標は反復回数で指定をする)

⑤置換した配列をシフトレジスタで次のループへ渡します。

⑥④と⑤がループ終了するまで繰り返される。

⑦10要素がすべて乱数の値で置き換わった配列になる。

ある特定の条件に合致(True)になった場合のみ、カウントアップするプログラムです。

Forループを10回行い、偶数の場合のみ数値をカウントアップさせています。

Forループが条件に合致した場合に終了または継続

Forループは指定回数だけ実行するのに使用するループですが、ループの途中で終了をさせることも可能です。

カーソルがオブジェクト選択の状態でForループの枠を選択し、右クリックを行ってください。上図のようなメニューが表示されます。

その中にある『条件端子』を選択してください。

条件端子に『True』を入力すると停止する場合

条件端子を選択するとForループの右下に赤丸と緑枠のアイコンが表示されます。

ブール値で『True』を入力すると、Forループが指定回数に達していなくてもループを終了します。

条件端子が出ると左上の『N』の所に赤丸が表示されます。条件端子の設定を行っているときはループの回数と、条件端子へループ入力を行わないと実行エラーとなります。

上図の場合は、『i』から3以上の値が出力されたときにForループを終了するというプログラムを組んでいます。

条件端子に『True』が入力されている間は継続する場合

条件端子をカーソルがオブジェクト選択で右クリックをすると、条件端子の終了条件を変更することが可能です。

デフォルトでは『TRUE』の場合にループは終了しますが、逆の『TRUE』の場合のみループを継続するという設定にすることも可能です。(FLASEになるとループを終了する)

プログラムの構成に合わせて条件端子を設定してください。個人的にはデフォルトTRUEの場合に終了を多用してます。

Forループの処理を並列化する

プログラムを組んでいると同じ様な処理を何度も繰り返す必要が出てきたりする場合があります。

上図のように100万回も計算をしていると処理の内容によっては時間を要するものも出てきたりします。

その場合、Forループを並列化することで処理時間を短縮化することが出来る場合もあります。

Forループの並列化は条件端子の時と同様にForループの枠をオブジェクト選択し、右クリックをするとメニューに『反復の並列化構成…』という項目が出てくるので選択をします。

Forループ反復並列化を構成するためのウィンドウが表示されるので、『ループ反復の並列化を有効』にチェックを入れます。

次に『生成される並列ループインスタンス数』の数字を並列したいループの数に変更します。

ここに入力された数字が並列の最大数となります。

※物理コアの数までしか並列化が出来ない。他に同時で処理しているスレッドがある場合、最大値で処理をすると影響が出る場合があるので注意が必要。

OKをクリックすると並列化の処理が完了します。

並列化をすると左上に『P』マークの並列インスタンスが表示されます。

Pマークが未配線または『ゼロ』が入力されている場合はLabVIEWが実行時に使用可能な論理プロセッサの数を決定して実行されます。

『-1』を入力すると、『生成される並列ループインスタンス数』の数でループが実行されます。他の処理を邪魔する可能性があるので注意が必要。

よく使用されている手法として、生成されるインスタンス数とは別に、プログラム的にインスタンス数を指定します。

『アプリケーション制御』⇒『CPU情報』⇒『CPU情報』という関数がありますので、CPU情報関数から使用しているPCの論理プロセッサ数を出力して、インスタンス数へ入力を行います。

もし、『生成される並列ループインスタンス数』が使用しているPCの論理プロセッサ数より多くても、CPU情報から論理プロセッサ数を指定することで、パソコンの能力以上のインスタンス数の割り当てを防げます。

Forループの並列化可能ループの見つけ方

Forループの並列化設定はどのプログラムでも行うことは可能ですが、逆にパフォーマンスを下げてしまう場合があります。

並列化が可能(効果がありそう)なループをLabVIEWでは自動的に並列化が可能なループを見つけてくれます。

ウィンドウメニューの『ツール』⇒『プロファイル』⇒『並列化可能なループを検索』で並列化が可能なループを検索することが出来ます。

検索をしたブロックダイアグラム上にあるForループが並列化可能または不可能かを検索してくれます。

緑のチェックが付いているものは並列化が可能で、?マークが付いているループは並列化出来るけど何らかの不具合が出るかもしれないという状態です。

例で上げた並列化の画像は『?』マークが付いており、何らかの不具合が出るかもしれないという判定になっています。(乱数が原因のようです。)

並列化した場合の実行速度の違い

LabVIEWの確認では並列化に『?』が付いていましたが、並列化を行い実行速度の確認を行ってみました。

並列化をせずに100万回ループを回した場合、実行に約19.9ms必要でしたが、並列化を行うことで、約6.5msに短縮が出来ています。

ちょっとした計算でもループの回数を重ねると実行速度に差が出てくるので、必要に応じて並列化を行っていく必要があります。

Whileループ

ループ回数の決まっていない場合(特定の条件でのみ終了)やプログラムを永続的に実行するための無限ループを行う場合にはWhileループを使用します。(決まった回数をループする場合はForループを使う)

Whileループの基本的な使い方

Whileループの基本的な使い方はWhileループ内にプログラムを書き、右下に出てくる条件端子へブール値を入力します。

条件端子は『Trueの場合停止』と『Trueの場合継続』のいずれかを選択する必要があります。個人的には『Trueの場合停止』を使用することが多いです。

ブールの制御器を条件端子に接続し、ストップボタンを押した場合にプログラムを停止するなどのプログラムを組むことが出来ます。

左下の『i』は反復回数が出力されます。初回は反復していないため『0』が出力されます。ループの実行回数を表示したいのであれば、インクリメントを反復回数に接続することで実行回数を表記できます。

条件端子へエラー配線を入力する

条件端子へはブールだけではなく、エラーも直接接続することが出来るようになっていまする。

過去はエラーをバンドル解除し、『Status』のみ出力をして条件端子へ入力するという形が取られていました。古いVIの中にはあったりします。

今はブールを条件端子へは直接ワイヤーを入力するのが主流となっています。(NIのCLD試験でもエラーバンドルを解除せずに直接入れることが推奨されています。)

実際にプログラムを組んでいく中で、エラーワイヤーだけを条件端子に繋ぐとWhileループを停止する条件がエラー発生時のみになるので、上図のようにOR関数にWhileループの停止させるためのブールとエラーワイヤーを接続するという手法をとります。

Forループの条件端子へも同様の処置は可能です。

データの入出力

データの入力

Whileループの外からデータを入力する場合は、Whileループの枠を選択するか、Whileループの中にある関数を選択することで入力をすることが出来ます。

または、Whileループ内の何もない場所でダブルクリックしても枠を選択したときと同じ入力状態になります。

何もない場所でシングルクリックを押した後にダブルクリックをするとWhileループ内にシングルクリックした場所まで不良ワイヤが発生します。

データの出力

内部から外へワイヤーを引くことで、出力側の端子にすることが出来ます。

端子を設置するための操作については入力側と同じです。

指標付け

Whileループ出力はデフォルトでは『最後の値』が出力されるように設定されていますが、Forループと同様に指標付出力を行うことも可能です。

指標付けを行うためには、Whileループの出力側端子にカーソルを合わせて右クリックを行うと、メニューが表示されます。

メニューの中から『トンネルモード』⇒『指標』を選択することで最後の値を指標付けに変更することが出来ます。

無限ループで更に待機関数の無い状態で指標付けを行うと配列データが巨大となり、使用メモリが膨れ上がるため『メモリが一杯』というエラーが発生します。

無限ループでの指標付けは避けてください。

指標付けの条件端子

指標付けに『条件』設定を設けることで条件に合致(True)した場合のみのデータを配列として出力させることが出来ます。

出力側の端子のトンネルモードを設定するときに『条件』にチェックを入れると出力端子の下に『?』マークが出現します。

出力側の端子を指標付にしている状態でで『?』マークにブール値を入力するとTrueが入力された場合の値のみを配列として出力をします。

例として上図は、100までに出現する偶数のみを配列データとして出力をします。

Whileループの反復回数が100以上になった場合に停止するようにしています。

反復回数が『0』でなく『偶数』の値の場合のみブール値がTrueになるようにAND関数を使用しています。

反復回数が偶数かどうかは商&余り関数を使用し、2で割ったときに余りが0の場合は偶数と判断しています。

前のループの値を次のループへ引き渡す(シフトレジスタ)

シフトレジスタという機能を用いることで、前のループで計算した値等を次のループでも使用することが出来ます。

トンネル端子にカーソルを合わせた状態で右クリックするとメニューが表示されるので、その中から、シフトレジスタと置換を選択します。

入力側にしかトンネル端子が存在しない場合は自動で出力側のシフトレジスタ端子が作成されます。

出力側にトンネル端子が有る場合は、トンネル端子を選択してシフトレジスタ端子に置換するか、新たにシフトレジスタ端子を作成するか選ぶことが出来ます。

シフトレジスタを使用してプログラムの例として、1ループごとに配列の指標0から要素を一つ削除し、配列のサイズを読み取って、配列サイズが0以下になった場合、ループを停止します。

最終的にシフトレジスタから出力される配列要素はゼロになります。

シフトレジスタに値を格納することで、次のループへ値を持ち越すことが出来るので、ローカル変数やグローバル変数を無理に作る必要は無くなります。