2012-03-03 6 views
1

私はクラスを持つオブジェクト:配分戦略は、以下のように

typedef struct grid_cell_type { 
int x; 
int y; 
grid_cell_type(int x0, int y0){ 
    x=x0; 
    y=y0; 
} 

} grid_cell。

私は約1億をこれらのキューに入れてポンピングします。次のように

は今のところ、これが起こる:

my_queue.push(new grid_cell(x0,y0)); 

すべてのこれらのオブジェクトの個々のピース単位の割り当ては、それはおそらくいくつかの質量配分ほど迅速ではないかのように思われます。

ここでベストプラクティスを考えていますか?

+0

ポインタを押す必要がありますか?値をプッシュして、ダイナミックメモリを自分で割り当てることによるトラブルやスピードの影響を抑えることができます。 –

+0

いいえ、ポインタは、新しい 'grid_cell'インスタンスをこのようなやり方でキューに入れる方法がわからないからです。 – Richard

+0

@リチャード:ちょうどこれをしてください: 'my_queue.push(grid_cell(x0、y0));' –

答えて

3

これらは小さく自己完結型のオブジェクトです。ポインターを置くのではなく、直接キューに入れます。実際に

  • 、64ビットシステムでとintを仮定は、ポインタがオブジェクト自体と同じ大きさであろう(それはたとえば、Visual C++の下で、である)、32ビットであります!したがって、バルクアロケータを持っていても、この価格を支払うことになります。
  • 一般的なメモリアロケータは時間的に高価なだけでなく、オブジェクトごとのオーバーヘッドを持ちます。この場合、オブジェクト自体が矮小になります(バルクアロケータには適用されません)。

あなたかなり効率的な「バルク」割り当て方式を考案できますが、私はそれが問題を回避し、完全に個々のオブジェクトの割り当てを回避するために簡単だと思います。

--- EDITは---あなたがこのようなstd::queueに要素をプッシュすることができ

std::priority_queueについて

struct grid_cell { 

    grid_cell(int x0, int y0) { 
     x=x0; 
     y=y0; 
    } 

    int x; 
    int y; 

}; 

// ... 

std::queue<grid_cell> q; 

q.push(grid_cell(0, 0)); 
q.push(grid_cell(0, 1)); 
q.push(grid_cell(0, 2)); 
q.push(grid_cell(1, 0)); 
q.push(grid_cell(1, 1)); 
q.push(grid_cell(1, 2)); 

、あなたはためにあなたがしたい方法を決定する必要があるだろうの要素。あなたのコード@Richard

--- EDIT 2 ---

はかなり異なっています。

  • pushごとに、コードはダイナミックメモリの新しいブロックを割り当てます。xyを割り当て)、ポインタをそのメモリブロックにキューに押します。
  • 私のコードは、queueによってあらかじめ割り当てられた大きなメモリブロック内の "スロット"にオブジェクトを直接構築します。すでに述べたように、小さな割り当てよりも多くの割り当てが少ないのは、 です。

あなたのコードです:メモリを起こしやすい

  1. をリークしますが、オブジェクトごとのオーバーヘッドがあるメモリの断片化が発生しやすい
  2. 、ポインタのための余分なストレージのために支払います、すでに述べたとおりです。

特殊なバルクアロケータは、最後の2つの問題を削除できますが、それらをすべて削除しないのはなぜですか?

--- EDIT 3 ---速度として

、一般的な動的メモリ割り当ては、高価(最良アロケータ約40~50マシン命令)です。

特殊なブロックアロケータははるかに高速ですが、メモリレイテンシの問題があります。すべてをうまくまとめておくと、キャッシュのローカリティが向上し、CPUのプリフェッチロジックに適しています。キューと実際のオブジェクトを参照しないでください。

+0

ポインタではなくキューに直接オブジェクトをプッシュする方法について考えてみましょうか?これのためのコードは私を避けています。 – Richard

+0

@リチャードあなたは 'deque'を使用していますか? –

+0

私は 'std :: priority_queue'をベクタを基本コンテナとして使用し、' std :: queue'をデフォルトのコンテナを基底として使用しています(これは 'deque'と信じています)。 – Richard

3

大規模な配列を1つ作成して割り当てることができます。

int allocation_index = 0; 
grid_cell_type* cells = new grid_cell_type[100*1000*100]; 
my_queue.push(&cells[allocation_index++]); 

それから億の少しニュースのオーバーヘッドを回避します。クリーンアップはdelete [] cells;と同じくらい簡単です。

EDIT:この特定のケースでは、Brankoが言ったことはおそらくあなたの最良の賭けです。 std::queueを使用していると仮定すると、必要なメモリが自動的に割り当てられます。私が提案したものは、より大きなオブジェクトに適しています。