DMA転送したデータをRAIDに確実に保存する
3月 15, 2012 コメントを残す
昨日は「DMA転送を確実に行う」ということで、 FPGA から ホストへの DMA 転送を行いました。今度は、その取得データを確実にファイルに保存したいと思います。
今回試した仕様は前回の仕様に加えて
仕様1:50MHz で変化する U16 データを 4ch 分 をFPGAからホストへ転送する。DMA転送レートは 400MB/s 必要。
仕様2:ストレージに確実にデータを保存する
構成を図示するとこんな感じです。FPGA から、CPUボード(ホスト)へは、400MB/s で DMA 転送ができています。今度はそのデータを、確実にストレージへ保存することが目的です。ホストからすると、400MB/s の読み込み、400MB/s の書き込みを行う必要があります。両方で 800MB/s のデータ転送が発生します。
そこで参考にしたのが、ともに開発している「ドルフィンシステム技術部 福島の開発日記」のこの記事「LabVIEW で高速にストレージに書き込む (3) – 高速に書き込めた!」です。
データの保存方法はいくつも方法があると思いますが、最も単純かつ高速な方法で書き込む方法を詳しくレクチャーされています。
引用させていただくと
上級ファイルI/O関数のちょっとしたパラメータで、全然ストレージスピードが変わってしまいます。
- ファイルを開く関数では、バッファリング無効
- バッファリングはキューを使って VI に流す
- バイトオーダーは OS 標準に合わせる (Windows なら little)
- データサイズの追加書き込みはしない
この4点を守ると最大6倍高速に書き込みできることが分かりました。
ということです。さっそく実装してみましょう。
まずは、同じVI でストレージ書き込みを実装してみる
まずは、先日の DMA転送の VI を改造して、以下のようなブロックダイアグラムを作成します。
中央の3つのループは上からそれぞれ以下のような役割です。
・DMA FIFO からデータ取得し、キューに入れる
・キューからデータを取得し、バイナリデータでファイルに書き込む
・その他モニタ用ループ (100ms)
まず、ファイルを開く関数では、「バッファを無効(F)」を制御器で制御してみます。
キューからの取得データを「バイナリファイルに書き込む」関数で、「配列…サイズを先頭に追加」「バイト順序」を制御器で制御できるようにしておきます。
まずは、この状態で実際に試してみます。
デフォルトの「big-endian」かつ、「バッファ有効」「先頭に追加」の状態です。
この状態ではやはり書き込みが間に合わず、キューが一杯になってきます。
では、参考記事の通りに、「little-endian」、「バッファ無効」、「先頭に追加しない」で実行してみます。
あれ?あまり実行速度に変化が見られません。
キューがすぐに一杯です。
要素数の問題かと考え、増やしました。具体的には 16384 から 524288 (512k) に増やしてみました。
やはりキューが増えていき、転送レートは 391M と若干悪いです。
では 要素数を 1048576 (1M) にしてみます。やはりキューに溜まって行ってしまいます。
ということは、2番目のループで時間がかかっていることはわかっています。
制御器をやめて定数にしてみました。
若干、キューへのたまり方が緩和されたみたいですが、まだ、だめみたいです。
これは、参考記事と同じように、書き込みの部分は完全に別 VI にしておくべきと考えました。
別スレッドの VI でストレージに書き込む
参考記事のように「StorageWriter.vi」を以下のように作成します。
「little-endian」、「バッファ無効」、「先頭に追加しない」をデフォルトに設定しています。
また、上記「StorageWriter.vi」を呼ぶメイン側の VI は以下のようにします。
フロントパネルはこんな感じです。
また、メモリが足りなくなるといけないので、一定数キューの数がたまったら停止するようにしています。
データ要素数は 524288 でやってみました。
結果、キューはたまらずにきちんとすべてのデータが書き込まれ、レートも400MB/s で転送できているようです。
要素数を減らしながら結果を見てみます。
要素数 |
結果 |
524,288(512k) |
問題なく 400MB/s で転送可能 |
262,144(256k) |
問題なく 400MB/s で転送可能 |
131,072(128k) |
問題なく 400MB/s で転送可能 |
65,536(64k) |
キューの増減が出始めるが、キューが深ければ 400MB/s で転送可能 |
32,768(32k) |
キューにデータがたまる一方で、400MB/s では転送が続けられない |
65536 ぐらいが 400MB/s で書き込める限界のようです。
逆に、キリの悪い数字(512 の倍数ではない場合)ではどうでしょうか。
要素数 |
結果 |
100,000 |
キューにデータがたまる一方で、400MB/s では転送が続けられない |
1,000,000 |
問題なく 400MB/s で転送可能 |
65536 以上でも、100,000 ではすぐにキューが一杯になってしまいます。
おまけ
上記の VI で、グラフを描画させたいと思い、モニタ用のループ(100ms毎)を追加しました。
実行してみると
問題なく、転送できました。
まとめ
参考記事の方法と同じく、
- ファイルを開く関数では、バッファリング無効
- バッファリングはキューを使って VI に流す
- バイトオーダーは OS 標準に合わせる (Windows なら little)
- データサイズの追加書き込みはしない
を守り、書き込み部は別 VI とすることで、FPGAからの 400MB/s のデータをストレージに確実に書き込めることが分かりました。