DMA転送したデータをRAIDに確実に保存する

昨日は「DMA転送を確実に行う」ということで、 FPGA から ホストへの DMA 転送を行いました。今度は、その取得データを確実にファイルに保存したいと思います。

今回試した仕様は前回の仕様に加えて

仕様1:50MHz で変化する U16 データを 4ch 分 をFPGAからホストへ転送する。DMA転送レートは 400MB/s 必要。

仕様2:ストレージに確実にデータを保存する

構成を図示するとこんな感じです。FPGA から、CPUボード(ホスト)へは、400MB/s で DMA 転送ができています。今度はそのデータを、確実にストレージへ保存することが目的です。ホストからすると、400MB/s の読み込み、400MB/s の書き込みを行う必要があります。両方で 800MB/s のデータ転送が発生します。

clip_image001

そこで参考にしたのが、ともに開発している「ドルフィンシステム技術部 福島の開発日記」のこの記事「LabVIEW で高速にストレージに書き込む (3) – 高速に書き込めた!」です。

データの保存方法はいくつも方法があると思いますが、最も単純かつ高速な方法で書き込む方法を詳しくレクチャーされています。

引用させていただくと

上級ファイルI/O関数のちょっとしたパラメータで、全然ストレージスピードが変わってしまいます。

  • ファイルを開く関数では、バッファリング無効
  • バッファリングはキューを使って VI に流す
  • バイトオーダーは OS 標準に合わせる (Windows なら little)
  • データサイズの追加書き込みはしない

この4点を守ると最大6倍高速に書き込みできることが分かりました。

ということです。さっそく実装してみましょう。

まずは、同じVI でストレージ書き込みを実装してみる

まずは、先日の DMA転送の VI を改造して、以下のようなブロックダイアグラムを作成します。

clip_image002

中央の3つのループは上からそれぞれ以下のような役割です。

・DMA FIFO からデータ取得し、キューに入れる

・キューからデータを取得し、バイナリデータでファイルに書き込む

・その他モニタ用ループ (100ms)

まず、ファイルを開く関数では、「バッファを無効(F)」を制御器で制御してみます。

clip_image003

キューからの取得データを「バイナリファイルに書き込む」関数で、「配列…サイズを先頭に追加」「バイト順序」を制御器で制御できるようにしておきます。

clip_image004

まずは、この状態で実際に試してみます。

デフォルトの「big-endian」かつ、「バッファ有効」「先頭に追加」の状態です。

この状態ではやはり書き込みが間に合わず、キューが一杯になってきます。

では、参考記事の通りに、「little-endian」、「バッファ無効」、「先頭に追加しない」で実行してみます。

あれ?あまり実行速度に変化が見られません。

キューがすぐに一杯です。

要素数の問題かと考え、増やしました。具体的には 16384 から 524288 (512k) に増やしてみました。

やはりキューが増えていき、転送レートは 391M と若干悪いです。

では 要素数を 1048576 (1M) にしてみます。やはりキューに溜まって行ってしまいます。

ということは、2番目のループで時間がかかっていることはわかっています。

clip_image005

制御器をやめて定数にしてみました。

若干、キューへのたまり方が緩和されたみたいですが、まだ、だめみたいです。

これは、参考記事と同じように、書き込みの部分は完全に別 VI にしておくべきと考えました。

別スレッドの VI でストレージに書き込む

参考記事のように「StorageWriter.vi」を以下のように作成します。

clip_image006

clip_image007

「little-endian」、「バッファ無効」、「先頭に追加しない」をデフォルトに設定しています。

また、上記「StorageWriter.vi」を呼ぶメイン側の VI は以下のようにします。

clip_image008

フロントパネルはこんな感じです。

clip_image009

また、メモリが足りなくなるといけないので、一定数キューの数がたまったら停止するようにしています。

データ要素数は 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毎)を追加しました。

clip_image010

実行してみると

clip_image011

問題なく、転送できました。

まとめ

参考記事の方法と同じく、

  • ファイルを開く関数では、バッファリング無効
  • バッファリングはキューを使って VI に流す
  • バイトオーダーは OS 標準に合わせる (Windows なら little)
  • データサイズの追加書き込みはしない
  • を守り、書き込み部は別 VI とすることで、FPGAからの 400MB/s のデータをストレージに確実に書き込めることが分かりました。

紹介 dolphinsasohの開発奮闘記
株式会社ドルフィンシステムで、デジタル信号処理、FPGA開発などを主に行ってます。 LabVIEW、FPGA、信号処理などその他いろいろ開発でのことを書き綴っていきたいと思います。

コメントを残す