2009-03-06 3 views
5

std :: vectorについて質問があります。ループの繰り返しごとにベクトルを消去します。最も効率的な方法は何ですか?

私は非常にメモリ集約的なアルゴリズムを使って、ベクトルサイズを予測し、ベクトルのために十分なメモリを予約しておくことで、メモリ使用量を減らすことができます。

次のうちどれが良いです:

for (...) { 
    std::vector<Type> my_vector; 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

またはこの:

std::vector my_vector; 
for (...) { 
    my_vector.clear(); 
    my_vector.reserve(stuff_count); 
    // Do stuff , and append stuff to my_vector. 
} 

ものを行うためのより良い方法がある場合に最適な私に教えて、またはしてください。

ありがとうございます!

+0

これは意見タイプの質問ではありません。特定のシステムの違いを測定する必要があります。 –

答えて

11

最初の変形では、通常は非常にコストがかかりますが、各反復でベクトルのバッファを再割り当てします。 2番目のバリアントでは、時折のみ再割り当てされます。速度があなたの優先事項であるため、2番目の方法が優れています。

要素の数がどこから分かっているのかは疑問です。たぶん、すべての反復で要素の最大数をすばやく計算し、これをバッファサイズに設定して、再割り当てしないでください。

+0

これは通常、非常にコストがかかる:それはプロファイリングなしの大胆なステートメントです。 C++メモリアロケータは、このような状況のために設計されているので、私はそれを疑っています(しかし、そのアサーションは大胆で、テストする必要があります)。 –

+0

さて、私たちはかつて同様の状況でプロファイルを立てなければなりませんでした。このような極端な場合の再割り当ては、約95%の時間を占めていました。バッファが割り当てられ、データがコピーされ、簡単に分析され、バッファが破棄されました。それはむしろ驚くべきことでした。 – sharptooth

+0

これは、高速実行を望む場合、不必要な再割り当てを避けるべきであるという結論に至ります。 – sharptooth

5

もう少し速いかもしれませんが、私は最初のクリーナーを見つけます。

+0

クリーンは大丈夫ですが、自分の状況では、アルゴリズムができるだけ多くの最適化を必要とするため、クリーンは問題になりません。私の最適化されていないテストでは、10GBのメモリを問題なく使用できます。 – Nailer

+0

それで、あなたはこのような質問をするべきではありません(誰もが非常に間違っているかもしれません)。あなたがすべきことは、コードをプロファイリングし、小さなデータセットで時間を計ることです。 –

5

コードの相違点は些細なので、両方のアプローチをテストして特定のアプリケーションに最適なものを確認してみましょう。

1

タイプがどのように構築/破壊される必要があるかによって、私は言うでしょう。それは破壊を必要としないPODがある場合は、ループ内のすべてのデストラクタを呼び出す、)(クリアをスキップして、代わりに静的配列としてそれを使用することができます。

std::vector<Type> my_vector(size); 
for (...) 
{ 
    int index = 0; 
    // Do stuff 
    my_vector[index] = some_value; 
} 

(警告:コード未検証)事前に のベクトルのための十分なメモリを確保

+0

もしそれがPODならば、私はどんな場合でも破壊を最適化するベクトルを期待します。パフォーマンスについての結論にジャンプする前にそれをテストしてください – jalf

+0

合意。 (Jalfと一緒に) –

+0

理論的には、あなたは正しい、Jalf。私の答えは、あなたが物事をたくさん破壊するかもしれないというヒントとして、おそらくそこで行うことができる仕事があるでしょう。 –

1

は...何... errは、メモリ使用量

を減らすことで私をたくさん を助けます!それはまったく意味がありません。メモリを予約しても、メモリの使用量を減らすことはできません。それは物事をより速くする一定の再配分の必要性を防ぎますが、限りの使用あなたは利益を得ません。

+0

実際、空きバイト数は等しくなりますが、割り当て可能な最大のチャンクは小さくなります。正しいサイズになるまで何度も何度も再割り当てすると、最終的にヒープが断片化します。最終的には。 – xtofl

+0

さらに、ベクトルは連続したメモリを持たなければなりません。したがって、現在のベクトルをもう拡張できない場合は、新しいブロック全体を割り当てる必要があります。古いベクトルはコピーされ、割り当てが解除されます。一時的に(oldsize + newsize)メモリーを使用します。膨大なメモリが必要な場合は、これが適切になります。 – Pieter

+0

ベクトルは、append関数を呼び出すときに必要なメモリの倍を割り当て、次の要素のための十分な空き領域がありません。これは、100要素のために十分な大きさのベクトルがある場合、101要素を追加するとベクトルが200要素分のメモリを割り当てられることを意味します。 – Nailer

6

私はベクトルサイズを予測し、ベクトルのための十分なメモリを事前に予約することで、メモリ使用量を減らすことができます。

占い師ではなくエンジニアのように行動してください。テストを作成し、その差を測定します。

0

多くの追加を行う必要がある場合は、std :: vectorの代わりにstd :: dequeを使用し、単に "push_back"を使用します。

0

どのようにですか?

std::vector<DataType> my_vector; 
my_vector.resize(sizeof(yourData)); 
memcpy(reinterpret_cast<char*>(&my_vector), &yourData, sizeof(yourData)); 
+0

なぜstd :: copy()なのですか? –

1

2番目のものは、ループを通してすべての使用の最大メモリ、つまりstuff_countの最大サイズを使用します。 std::vector::clear() does not necessarily free memory。つまり、をstd::vector::clear()の前後に呼び出すと、標準に準拠した実装で同じ値が返される可能性があります。

上記のスキームでメモリを割り当てる回数を減らすことをお勧めします。しかし、あなたは確かにいつでもメモリフットプリントを減らすことはありません。全体的な効果は同じになりますから、

std::vector<type>().swap(my_vector); 
my_vector.reserve(stuff_count); 

またはあなたの最初のソリューション:あなたはメモリの予約量を​​縮小したい場合は、ベクトルのスワップイディオムを使用する必要があります。

関連する問題