std::vector
膨大な数の要素を32ビットで(unsignedintで許可されている2^ 32-1以上)に格納する必要があります。私の知る限り、この量はstd::size_t
unsignedint型によって制限されています。std::size_t
にキャストしてこれを変更してもunsigned long
いいですか?問題は解決しますか?
それが不可能な場合は、64ビットでコンパイルするとします。それは変更なしで問題を解決しますか?
std::vector
膨大な数の要素を32ビットで(unsignedintで許可されている2^ 32-1以上)に格納する必要があります。私の知る限り、この量はstd::size_t
unsignedint型によって制限されています。std::size_t
にキャストしてこれを変更してもunsigned long
いいですか?問題は解決しますか?
それが不可能な場合は、64ビットでコンパイルするとします。それは変更なしで問題を解決しますか?
size_t
は、割り当て可能なメモリチャンクのサイズを保持できるタイプです。したがって、自分に収まる以上のメモリを割り当てることはできずsize_t
、したがって、どのような方法でもより多くの要素を格納することはできません。
64ビットでコンパイルすると可能になりますが、配列がメモリに収まる必要があることに注意してください。2 32は40億なので、4 * sizeof(element)GiBのメモリを超えることになります。8 GiBを超えるRAMはまだまれであるため、妥当とは思えません。
ベクトルをSTXXLのものに置き換えることをお勧めします。外部ストレージを使用するため、ベクターはRAMの量によって制限されません。ライブラリは、テラバイトのデータを簡単に処理できると主張しています。
(編集)衒学的な注意:size_t
最大の単一オブジェクトのサイズを保持する必要がありますが、必ずしもすべての使用可能なメモリのサイズである必要はありません。セグメント化されたメモリモデルでは、各オブジェクトが単一のセグメントに存在する必要がある場合にのみオフセットに対応する必要がありますが、セグメントが異なると、より多くのメモリにアクセスできる場合があります。「長い」メモリモデルであるPAEを使用してx86で使用することも可能です。しかし、実際に使っている人は見たことがありません。
言うべきことがたくさんあります。
まず、32ビットシステムと64ビットシステムのそれぞれのサイズについてです。std::size_t
これは、規格が述べていることですstd::size_t
(§18.2/ 6,7):
6型
size_t
は、実装で定義された符号なし整数型であり、任意のオブジェクトのバイト単位のサイズを含めるのに十分な大きさです。7 [注:すべての可能な値を含めるためにより大きなサイズが必要な場合を除いて、実装では整数変換ランク(4.13)がそれ以下のタイプ
ptrdiff_t
を選択することをお勧めします。—エンドノート]size_t
signed long int
このことから、32ビットシステムでstd::size_t
は少なくとも32ビット、64ビットシステムでは少なくとも64ビットのサイズになります。それはもっと大きくなる可能性がありますが、それは明らかに意味がありません。
第二に、型キャストのアイデアについて:これが機能するためには、理論的にも、それが発生する場所に関係なく、それ自体の実装内で型をキャストする(またはむしろ再定義する)必要があります。std::vector
第三に、「32ビットの」この超大型ベクトルが必要だと言うとき、それは32ビットシステムでそれを使用したいという意味ですか?その場合、他の人がすでに指摘しているように、32ビットシステムにはそれほど多くのメモリがないため、必要なことは不可能です。
しかし、第4に、64ビットマシンでプログラムを実行し、要素の数を参照するために32ビットデータ型のみを使用する場合、合計サイズを参照するために64ビット型を使用する場合もあります。バイト単位の場合、std::size_t
要素の総数と個々の要素のインデックスを参照するために使用されますが、バイト単位のサイズは参照されないため、関係ありません。
最後に、64ビットシステムを使用していて、のように機能する極端な比率のものを使用したい場合std::vector
、それは確かに可能です。32 GB、64 GB、または1 TBのメインメモリを備えたシステムは、おそらくそれほど一般的ではありませんが、確実に利用できます。
ただし、このようなデータ型を実装するには、次のような理由から、1つの連続したブロックにギガバイトのメモリを単純に割り当てることは一般的にお勧めできません(これが実行されます)。std::vector
結論
A) 32ビットシステムを使用していて、これほど大きなベクトルを使用したい場合は、@JanHudecによって提案されたようなディスクベースの方法を使用することが実行可能な唯一の方法です。
B)数十または数百GBの大規模な64ビットシステムにアクセスできる場合は、メモリ領域全体をチャンクに分割する実装を検討する必要があります。基本的に、のように機能するものでstd::vector<std::vector<T>>
、ネストされた各ベクトルは1つのチャンクを表します。すべてのチャンクがいっぱいの場合は、新しいチャンクなどを追加します。これにもイテレータタイプを実装するのは簡単です。もちろん、これをさらに最適化してマルチスレッドとNUMA機能を利用したい場合は、ますます複雑になりますが、それは避けられません。
Avector
はあなたにとって間違ったデータ構造かもしれません。のサイズによって制限されるメモリの単一ブロックにストレージが必要ですsize_t
。これは、64ビットシステム用にコンパイルすることで増やすことができますが、32ビットシステムで実行することはできません。これは要件となる可能性があります。
vector
の特定の特性(特にO(1)ルックアップと連続メモリレイアウト)が必要ない場合は、などの別の構造std::list
が適している可能性があります。これは、リンクリストであるため、コンピュータが物理的に処理できるものを除いてサイズ制限がありません。便利にラップされたアレイの。