2

私は基本的にCが初めてです。

64 GB RAM と 240 GB SSD を搭載した 64 ビット Windows7 を使用しています。

取得したデータを 2 つの内部 FIFO に保存し、そのデータを RAM に渡す取得ボードを使用します (つまり、60 GB のデータを取得できる可能性があります)。

私ができないことはfwrite、4 GB を超えるサイズのバイナリ ファイルを書き込むために関数を使用することです。

ここに私の変数があります:

static UINT64      *rbuffer12 = NULL;
static UINT64      *rbuffer34 = NULL;
FILE               *fd_raw, *fd_raw2;
UINT64             nacq = 2000;
ICS1555_ULONG_T    bufferLength12, bufferLength34;

そのため、FIFO #1 で何が起こっているかに注目すると、ボードはnacqサイズを取得bufferLength12し、 が指すメモリを使用してすべてのものを RAM に格納しrbuffer12ます。

bufferLength12 = 524288;
acq_length = 524288 / (channels_number * 2 * 4);
nBytes = bufferLength12 * 4;

rbuffer12 = (UINT64 *) malloc(nacq*nBytes);
memset(rbuffer12, 0, nacq*nBytes);

for (i = 0; i < 4*nacq; i++)
 ReadF(h, 0, (UINT64 *) (rbuffer12 + i * bufferLength12/8), nBytes/4, NULL, 0))

にデータを書き込みたいと思いますFile12.bin

fd_raw=fopen("File12.bin","wb")
fwrite((UINT64 *) rbuffer12,8,(nacq * 4 * channels_number * acq_length) ,fd_raw);
fclose(fd_raw);
fd_raw=NULL;

を設定するnacq=2000と、ファイルサイズは 4'096'000 バイトです。この値を増やそうとすると、プログラムがハングし、取得を中止すると、たとえば 1'960'000 バイトの次元を持つバイナリ ファイルが取得されます。

より大きなバイナリ ファイルを取得するにはどうすればよいですか?

4

3 に答える 3

8

コメントで、コンパイラが MSVC 2008 であり、x64 をターゲットにしていると述べています。

ランタイム ライブラリのバグに巻き込まれたのではないかと思います。たとえば、次の投稿を参照してください。

4GB を超えるデータを書き込むことはできますが、1 回の呼び出しで行うことはできませんfwrite。一度に 4GB を超えないように複数の呼び出しを行う必要があります。

いずれにせよ、それは確かにあなたの問題へのより良いアプローチです。現在のアプローチでは、1 つの巨大なメモリ ブロックを割り当てる必要があります。この回避策により、より小さいメモリ ブロックを割り当てることができるため、システムのメモリに対する要求が少なくなります。

于 2013-09-09T09:09:42.617 に答える
2

他の答えはほとんどすべてをカバーしています。あなたは自分が思っていることをしていないことを指摘したいと思います。特に、物理 RAM 内のすべてのページは、ページング ファイル (スワップ ファイル) 内のページによってサポートされることに注意してください。インメモリ配列にデータを書き込む場合、書き込む各ページは、書き込み時に 1 回だけアクセスされます。その後、取得が完了して書き出すまで、しばらく使用されません。オペレーティング システムは、ユーザーがデータを使用していない間、背後でデータをディスクにページ アウトします。

ファイルに「書き込む」ときに行うことは次のとおりです。

  1. バッファの先頭でデータにアクセスします。このデータは非常に古いため、この時点でディスクにページアウトされる可能性があります。同時にディスクにあるにもかかわらず、まだ RAM にある可能性があります。これは、最新の OS が古い RAM をディスクに常にスピルしてハイバネーションを高速化しているバッテリ駆動のシステムである可能性があります。RAM に存在しない場合は、オペレーティング システムがページ フォールトを処理し、データを読み戻します。

  2. ファイルに書き出します。ディスクの別の場所に戻ります。

したがって、データはディスクからディスクへの往復を行います。これはおそらくあなたが望むものではありません。

3つの方法で処理できます。

  1. システム全体のページング ファイルを使用する代わりに、OS がファイルをページング ファイルとして使用できるようにします。ファイルをメモリマッピングしてから、メモリに書き込むだけです。マッピングを閉じると、すべてのメモリ ページがファイルに保存されることが保証されます。往復はありません。

  2. 2 つのスレッドとインターロックされたバッファーのセットを用意します。1 つのスレッドがバッファーをいっぱいにし、もう 1 つのスレッドがバッファーをディスクにダンプします。インターロックは、両方のスレッドが rsch の他のつま先を踏むのを防ぎます。これにより、winapi にあまり慣れていない場合に対処しやすいブロッキング コールを使用できます。

  3. スレッドは 1 つですが、ノンブロッキング I/O を使用します。そうすれば、データが実際にそこに到達するのを待たずに、ディスクに「書き込む」ことができます。それを支援するライブラリがそこにあり、boostは 1 つの良い選択かもしれません。

于 2013-09-09T12:24:41.470 に答える