私は主にの生存率に興味があり、そのような配列を縮小しています。ダイナミックに割り当てられた2D配列でrealloc()を使用するのは良い考えですか?
私は個々の適度に大きな2D配列を作成するために、単一のmalloc()呼び出しを使用したプロジェクトに取り組んでいます。 (それぞれ最大で数十MiBです。)配列の1つのライフにわたって、その内容は劇的に(半分以上)縮小します。明らかに、私はプログラムの寿命のために配列の大きさだけを残すことができます。 (GiBのRAMが利用可能なシステムでは、x MiBしか使用できません)しかし、私たちは、プログラムが終了する前に割り当てられたスペースの半分以上が使用不能になっていると話しています。配列を使用すると、生き残っているすべてのデータは連続した行セット(ブロックの先頭)に保持されます。もし私が本当にそれを必要としなければ、すべてのRAMを保持することは無駄に思えます。
動的に作成された配列を縮小するためにrealloc()を使うことができますが、2D配列はもっと複雑です。私はそれを構成する関数を実装したので、そのメモリのレイアウトを理解していると思うが、これは言語の理解とコンパイラの動作の限界を押し進めている。明らかに、私は行だけでなく行ポインタを扱わなければならないでしょうが、これはすべての結果がどのように予測できるかわかりません。
そして、はい、私は単一のmalloc()で配列を作成する必要があります。問題のオブジェクトには、数百万行があります。私は別々に各行をmalloc()するループを使用しようとしましたが、プログラムは常に約100,000のmalloc()で凍っていました。
char ** alloc_2d_arr(int cnum, int rnum) {
/* ((bytes for row pointers + (bytes for data)) */
char **mtx = malloc(rnum * sizeof (char *) + rnum * cnum * sizeof (char));
/* Initialize each row pointer to the first cell of its row */
char *p = (char *) (mtx + rnum);
for (int i = 0; i < rnum; i++) {
mtx[i] = p + i * cnum;
}
return mtx;
}
'realloc'はこのような大きなテーブルのためには良いアイデアではなく、" avl "と" red-black "ツリーを見てください。 –
"本当に必要ない場合は、すべてのRAMを保持するのは無駄なようです。" - 最初の*プロフィール*。第二に、reallocは、すべてのあなたの内部のデータを別のページにコピーするトリガーとなる高いリスクを冒しています。ラムを保存しようとする理由だけで発生する些細な費用はあなたが本当に問題ではないと主張します。ここでの唯一の勝利シナリオは、メモリベースと同じリージョンヘッドを保持する 'realloc 'であり、他の用途のためにテールページが返されます。何か 'realloc'は保証がありません.... – WhozCraig
...代わりに、2つ(または3つか4つ)の割り当てを考えて、あなたが最終的にどのものを保持しているかを覚えておいてください。' free() ' - 一度イベントが起これば、もはや必要のないものを送りますか?私。あなたの行列の "保存された"半分が最初の割り当てにあり、後半は別の割り当てにあり、最終的には後半だけ解放します。 – WhozCraig