2

次の変数があります(簡略化されたケース):

std::array<std::array<float, 4>, 4> matrix;

プログラムの関数からこの変数を返す必要があります。値として使用std::unique_ptrまたは返すことができます(自動メモリと動的メモリ)

私のプラットフォームの float のサイズは 4 バイトで、16 の位置があるため、サイズは16 * 4 = 64バイトになります。

カスタム アロケーターなどを使用しない動的メモリは、一般的に低速であることに加えて、メモリの断片化を引き起こす可能性があるため、自動メモリと動的メモリとしてデータをやり取りする実際の制限はどのくらいになるのでしょうか? 動的メモリの使用を開始するには、どのサイズから始めればよいですか? 質問は答えられませんか?

4

5 に答える 5

2

init関数の結果としてこのような構造体を返すサイズが心配な場合は、私はしません(そのステートメントへの警告(不明な場合はいつでも測定できます))。

最新のコンパイラはすべて、すでにRVOとNRVOの最適化を行っています。その結果、値で返してもコピーは作成されません。コンパイラーは、結果が特定の宛先に送信されることをすでに認識しており、コピーを省略して、宛先に配置されています。

したがって、サイズの制約は実際には問題ではありません。

また、C ++ 11では、移動セマンティクスの概念が導入されました。したがって、値で戻る必要はありませんが、移動で戻る必要があります。ほとんどのstdコンテナでは、これはいくつかのポインタを交換することを意味します(残念ながら、これはstd :: arrayでは役に立ちません)が、一般的にはうまく機能します。

だから私にとって、それはおそらく価値によるリターンでしょう。その構造をクラスでラップすることもできますが。そうすれば、現実が噛み付き、それが多くの費用がかかる場合、コードを変更せずに補償するためにクラスを内部的に変更することができます。

于 2012-10-22T20:40:54.920 に答える
0

パフォーマンスの低下を実際に観察し、それをこのコードにトレースしましたか?これが単なる理論上の質問である場合は、直感的で自然に見える方法で実際にコーディングすることをお勧めします。

それを実行し、すべての問題を解決したら、プログラムを実行して、達成したパフォーマンスが許容できるかどうかを確認できます。そうでない場合は、想像上のボトルネックではなく、実際のボトルネックの最適化に取り掛かることができます。

ドナルド・クヌースはそれを最もよく言いました:「私たちは小さな効率を忘れるべきです、時間の約97%と言います:時期尚早の最適化はすべての悪の根源です。」

于 2012-10-24T08:17:34.117 に答える
0

スタックに 64 バイトをコピーするのは安価です。64 バイトを割り当てるよりも確実に安くなります。ヒープに割り当てられた寿命の短い変数に unique_ptr を使用すると、ほぼ確実に効率が低下します。

関数を呼び出してすぐに戻り値を使用すると、高速になります。行列を返す関数のチェーンを介して行列を伝播することを計画している場合にのみ、効率の損失が大きくなります。メモリの割り当てと unique_ptr の使用の実現可能性は、データの実際のサイズに依存するよりも、データが再返される回数に依存します。

于 2012-10-24T08:39:32.357 に答える
0

64 バイトの割り当てを行うことで断片化が発生する可能性はないと思います。32 ビット環境で大規模なアプリケーションを使用した私の経験では、16 MB を超える割り当ては、断片化の問題により失敗する場合があります。割り当てが断片化を引き起こすには、割り当てが長期間存続する必要があります。サーバー コードの場合、これは数日以上かかります。64 ビット環境では、フラグメンテーションが発生する可能性は低くなります。

パラメータを値で渡すということは、コピーを作成することを意味します。これは効率的ではありません。推奨される回避策は、参照を使用することです。サイズについてはよく知られた制限はありません。

私の経験から、PC のようなプラットフォームには次のことをお勧めします。

  • 変数のサイズが 100 バイト未満 - 値渡し。
  • var のサイズが 1 KB を超えています - 参照を使用し、コピーを避けてください。

中間の値は、どちらの決定でも問題ないグレー ゾーンのようなものです。繰り返しますが、これらの数字には魔法の意味はありません。いくつかの合理的な参照。

ヒープ割り当ての代わりに参照を使用することを検討することをお勧めします。

于 2012-10-22T20:09:29.757 に答える
-1

これに動的配列を使用するのはやり過ぎです。16 個の float を保持するために 64 バイトを割り当てるだけではありません。配列に 4 つのメモリ ブロックを割り当てています。それぞれにヒープ管理用のヘッダーと C++ ごとの配列サイズがあり、メモリ アロケータは通常、要求したものよりも大きなブロックを使用し、多くの場合ブロック境界に配置されます。

次に、各配列を保持する構造体のオーバーヘッドがあります。例えば。各 std::array は、オブジェクトへのポインターを保持するクラスです。最小で 8 バイト (ポインターの場合は 4、配列の長さの場合は 4) x5 です。

そして、あなたには参照の局所性がありません。マトリックスの各行は、メモリ内で互いに遠く離れている可能性があります。それらがすべて隣り合っている場合、それらは単一のキャッシュラインで読み取られます。

あなたはただ使う方がずっと良いです:

float matrix[4][4[

オブジェクト指向が必要な場合は、クラスにラップします。

class Matrix44 
{
    float matrix[4][4];
}

これにより、はるかに効率的になります。

于 2012-10-22T20:16:37.483 に答える