1

素数を.txtファイルに書き込むC++で素数ファインダーを作成しましたが、102,144,001番目(2,084,058,601)を見つけた後にクラッシュしました。また、見つかった素数をベクトルに格納するため、現在チェックされている数値の平方根よりも小さいすべての数値で除算する必要はなく、素数のみで除算できます。(10,240n + 1)番目に見つかった素数の後に素数を格納するベクトルのサイズを変更し、102,144,001は10,240n + 1であるため、サイズ変更中にクラッシュしました。ベクトルunsigned__int64を使用しているため、クラッシュ時に約780メガバイトを使用しましたが、8GBのRAMがあります。vector.reserve()を使用する必要がありますか?(50分後にもう一度クラッシュしたくない...)

4

3 に答える 3

3

まあ、利用可能なメモリは使用可能なメモリと同じではありません。

cppreference、ベクトルの要素が連続して格納されることを示します。したがって、RAMの量ではなく、プログラムの実行時に連続したRAMの量が問題になります。ベクトルが連続している必要がある場合、ベクトルは連続メモリの使用可能な最大セクションを超えて拡張することはできません。

その結果、ベクトルのサイズ変更が必要な場合にも問題が発生する可能性があります。ベクトルが隣接するメモリの大きなブロックに隣接している場合、それは拡張できます。ただし、ベクトルが小さすぎるブロックにある場合は、それ自体を新しい場所にコピーする必要があります...これには時間がかかります。

dequeコンテナは、連続した保管場所を必要としないため、より適切な選択となる可能性があります。これにより、使用可能なRAMをより多く使用できるようになり、サイズ変更中のコストのかかるコピー操作を回避できます。

(標準がベクトルが連続していることを保証しているかどうかが心配な場合(したがって、OPの問題につながる可能性があります)、これを読むと、問題に光を当てるのに役立つ可能性があります。)

于 2012-11-23T23:33:36.347 に答える
1

2084058601の平方根よりも少ない4730素数しかありません。その少量のデータを格納しているときにメモリが不足している場合は、何か問題があります。

私は最近素数ジェネレーターを作成し、それを使用して最初の10億個の素数を合計しました。エラトステネスのセグメント化されたふるいを使用し、各セグメントの先頭に追加のふるい分け素数を追加します。メモリ使用量はビット配列のサイズに対して一定であり、ふるい分け素数に対してゆっくりと増加します。あなたはそれを見てみたいかもしれません。

于 2012-11-23T23:43:47.187 に答える
0

正直なところ、それがあなたの問題だとは思えません。64ビットOSでは、十分なアドレススペースが必要なので、スワップが不足した場合にのみ問題が発生するはずです。

あなたの問題はフェンスポストの問題だと思います。サイズを変更する必要があるとさえ思っているという事実、chainpush_backは十分すぎるはずです。

クラッシュの詳細はおそらく一見の価値があります。また、メモリを割り当てることができない場合にstdvectorがスローする例外を確認することもできます。もう1つの懸念は、ioが計算よりもはるかに遅くなる可能性があることです。クラッシュした場所ではなく、クラッシュした場所が最後の桁までわかっている場合は、印刷が多すぎる可能性があります。

于 2012-11-24T01:13:52.957 に答える