みなさん、こん××は。
Visual C++.NETでデータ取得制御プログラムを書いています。
①トリガーがかかるとAD変換(8bit)、データ数65536ポイントを行います。
②繰り返しは100Hzで、1トリガー毎にPCI,IEEE1394経由でリムーバルHDDに書き込みます。
③1000回トリガーをかけてデータを取得します。
別の命令実行後、①、②、③を繰り返します。
問題は、HDDにデータを書き込む速度がネックとなり、データ保存が完全にできて
いない事です。出来れば、1000回トリガー分のデータ取得と保存がに終了するまで、
別の命令を実行させないようにプログラミングしたいと考えています。
通常は、どのようにプログラミングするものなのでしょうか?適当なループ等作
って回したらよいかとも考えたのですが...。アドバイスをお願い致します。
処理内容はわかりますが、そもそもこの処理を始めるトリガーは
いったい何なんでしょう?
他の命令を実行させないとはいったい何を指していますか?
GUIが絡むのであれば、使用しているGUIの説明までしましょう。
まだ情報が足りないと思います。
局部的な処理だけでなくてそのアプリの全体像がわかる形で
情報を提示してください。
処理中のディスクアクセス速度が問題なだけなら、
毎回書き出しせずにメモリ上にでも保存しておいて
処理完了後にまとめて書き出せばいいと思うのですが、
そういうレベルの話ではないのでしょうか。
> 別の命令を実行させないようにプログラミングしたいと考えています。
具体的な手段は提示された情報だけでは特定できませんが、
もしこれが必要なら、「排他制御」するか「実行プライオリティを
引き上げる」のが普通だと思います。
とはいえ、いわゆるリアルタイム OS ではありませんから、
自プロセス内での制御ならともかく一ユーザプロセスから
既存の他プロセスを全部止めたりは出来かねますが....。
100Hzということは、10msec間隔ということですね。
まず、AD変換してコンピュータに取り込む方法が記述してありません。
何かAD変換ボードをお使いなのですか?
10msec間隔でタスクが必ず動く保証は無いでしょう。
ここがリアルタイムOSじゃないので難しい。
OSやハード上の問題が無ければタイマー割り込み/スリープを使ってください。
あと、タスクの優先度を高く設定してみて下さい。
PATIOさん
トリガーは、外部からADボードに直接パルスが入ってきます。立ち下がりで、
ADを開始します。他の命令とは、ステッピングモータを指定位置まで移動
させる命令です。プログラムは、ダイアログベースで作成しています。
命令の流れとしては、
①モータ制御開始チェックボタン
②計測開始チェックボタン
③トリガーの有無判断
②AD変換開始
(ここで、1000回のデータを保存するまで待ちたいです。)
③モータ移動
④②、③を指定回数分繰り返し、終了
です。「1000回のデータを保存」と「指定回数分繰返し」で、2重ループに
なってます。
データ保存を確実にということであれば、モータの移動スピードを落として
時間を確保するという手もあるのですが、計測時間がかかりすぎてしまうので、
問題にしています。よろしくお願い致します。
私の記憶が正しければWindowsカーネルの
クァンタムタイムは20msecだったと思います。
コンテキストスイッチ自体がこれ以上正確に動かないので
当然これ以上の精度の動作はできません。
システムプロパティーのパフォーマンスオプションで
アプリケーション/バックグランドサービス
の切り替えができますが、、
これによってクァンタムタイムが変わった気が・・・
--------------------------------------------------
余談:
Linuxで簡易ネットワークアナライザーを作った時には
カーネルソースのクァンタイム値を変えて、カーネル再構築をしました。
まあ、その位の問題です。
--------------------------------------------------
話をまじめに考えていないので間違っているかもしれませんが・・・
1秒間に6.4MBのデータが発生し、
(何秒間隔かわかりませんが)1000回データ取得をするので
6.4GBのデータを格納する処理はキツイってことですよね?
さて、この6.4GBのデータが発生していく段階で、
ハードディスクの書き込み速度(シークタイムから計算される理想値)が間に合わず、
物理メモリー領域から溢れてしまうようだと、それはハードの限界です。
RAIDするなり、メモリーを足すなりしてください。
値が収まっているならば、ソフトでなんとかなるかもしれません。
--------------------------------------------------
ココから先は、希望が有れば詳しく説明しますが、、一応、手順だけ。
・メモリー上にディスクにキャッシュされない領域を確保する。
(つねにコミットされており、アクセス時にページフォルトが発生しない)
・上記領域の管理は自分でする。多分64k毎のページに分けるのが吉
・データ取得のスレッドのプライオリティーを上げる。(上記の領域に書き込んでいく)
・データ書き出しの部分は、必要なら(CPUが辛ければ)
「I/O完了ポート」によって、スレッド数を管理し、コンテキストスイッチを減らす。
追記:
パフォーマンス切り替えは多分
「アプリケーション」
の方がクァンタムが短いハズ。(GUIは即応性が要求されるので)
で、上で説明したプログラムのスレッド構成は
・データ取得スレッド1
・データ書き出しスレッド1~多
です。
まだ想像が入ってますが、
問題点は、
一回64kbyteのデータを10ms間隔で1000回取り込む。
取り込んだ後、ファイルに書き出しているが時間がかかって
次の取り込み開始までに間に合わない。
そう解釈して良いんですか?
問題はステッピングモータの制御と次の取り込み開始との関係ですね。
ステッピングモータの制御と取り込み開始の間に関係が無いのであれば、
ステッピングモータの制御を行った後、取り込み開始を待てばよいだけだと思います。
ステッピングモータの制御開始はなにがトリガーでしょう?
ファイル書き込みが同期で行われているのであれば、
基本的に出力が終わるまで関数から返ってこないのではないですか?
ステッピングモータの制御の開始に別のトリガーを設定しているのであれば解りますが、
一連のプログラムの流れで保存の後、制御となっているのであれば、
制御が開始された時点で少なくともOSにデータは引き渡されていると思うので
何処が問題なのかわかりません。
少なくとも書き込み関数から帰ってきた段階であれば、
メモリ上の情報を一旦破棄して、再度メモリ上にデータを格納しても問題は起こらない
はずです。
各動作のトリガーが何で、動作間の関係がどうなっているのかが提示されていません。
あなた自身にとっては当たり前の事でも読んでいる方にとっては雲を掴むような話です。
動作と動作の間はどう繋がりますか?
各動作は独自のタイミングで動作しているのですか?
おや、10秒かけて64MB取るってことかな?
勘違いしてましたよ、、
じゃあ、ページフォルトさえ起こさなければ、余裕でメモリに入りますね。
最初に64MBのメモリ確保をしてしまえば良いですね。
ただ、10msecはかなりタイトなので、ページングの対象にならない領域を確保しなきゃならな
い。
VirtualAlloc() 及び VirtualLock() を使えば性能問題はほとんど解決かと・・・
以下の文が疑問なのですが
>①トリガーがかかるとAD変換(8bit)、データ数65536ポイントを行います。
10msecでデータ数65536ポイントということは1ポイントあたりの処理が15usec程度
しかないんですが、ボードとのI/Fで可能なの?
65536ポイントのデータって想像つかないんですが、オーバースペックじゃないの???
10msecでデータ数65536ポイントということは1ポイントあたりの処理が15usec程度
しかないんですが、ボードとのI/Fで可能なの?
失礼 15usec→0.15usecの誤りです。
まず、不可能と思います。
う~む、、冷静に考えると6.4MHzのサンプリング周波数ってキツイですね
ただ、所詮はこれ以上のクロックと反応する回路が
あればハード的に出来てしまう所なのでできなくは無さそうに感じます。
オシロスコープなんかは余裕でやってますしね。
(最近はデジタルの奴があるみたいね)
どちらにしろ、「もじもじくん」さんの答えが欲しいところですね。
あら、私はまた、いっぺんに64Kbyte返って来るのかと思ってました。
10msで64Kbyteの転送って秒間で6400Kbyteですね。
PCIスロットってどのくらい行けるんでしたっけ?
ご本人に背景からひっくるめてやっている事を説明してもらった方が
速そうですね。
まだ、不明点がかなりあるようですし。
もし、データを収集することが可能であれば、最初にメモリを64MB確保して、
メモリに保存しておき最後にHDDへ書き込む。
PCは、IBMのデスクトップ(メモリーは、512MB積んでいます)
全体的なプログラムのながれは、
for(i=0;i<任意に設定する;i++)(何セット計測するか決めている)
{
モータ移動(トリガーに関係なし、指定の位置にモータを移動させるだけ)
for(j=0;j<1000;j++)
{
AD変換(8bit, 65536)(外部トリガーによりAD、サンプリング周波数は500MHz、ADボ
ードには2MBのオンボードメモリー)
ファイルに保存
}
}
です。
モータ移動させて、100HzのトリガーがADボードに入り、AD変換(8bit、65536ポイント)
AD変換直後に、1トリガー毎にファイルに保存しています。トリガはADボードだけに与えて
います。モータは特にトリガーと関係ありません。
PATIOさんの「一連のプログラムの流れで保存の後、制御となっているのであれば、
制御が開始された時点で少なくともOSにデータは引き渡されていると思うので何処が
問題なのかわかりません。」というご指摘を受けて再度ファイル内のデータについて
ファイルのバイト数と制御プログラムから保存すべき1トリガーあたりのバイト数から
調べてみたところ、データは全て保存されていたことがわかりました。
読み出しファイルのプログラムが悪く、勘違いしてしまいました。保存したファイル(2.5GB
ほどあります)を使って保存したデータを読み込むためにfseek関数を使っているのですが、
オフセット設定の定義longであるため、オフセット値の最大数を超えてしまい、file seek
errorとなり、データ保存出来ていないと判断していました。大変お騒がせしました。
すいませんでした <(- -)>、<(_ _)>、<(- -)>、<(_ _)>。
アイススケーター、Bosscatさんがご指摘の転送速度がネットになっているのだと思うのです
が、
HDDへの書き込みが遅く、命令が終わっていても、4,5分はデータを保存し続けていまし
た。
上のfor分で「任意に設定する」を100とか設定してしまうと、バッファーからデータがあふれ
て
しまい、今度は本当にデータが完全に保存されないのではと考えています。
とりあえず、対策としてはHDDへの書き込み速度をみて、モータの移動速度を遅くしたり、
タイマー等(SetTimer関数で良いのかな?)を使い、時間稼ぎしてみようと思います。