64 ビット UNIX OS を使用している場合、配列のサイズを 8 の倍数に定義する利点はありますか? この配列を使用して、共有メモリからデータをロードするつもりです。そのため、オペレーティング システムとページ サイズに依存関係が存在する可能性があります。
3 に答える
関係ない。コンパイラは、そこにパディングが必要かどうかを知っているので、決定させてください。当て推量のためにコードを混乱させないでください。
最初にプログラムを動作させてから、プロファイラーでパフォーマンスに注意してください。
メモリアクセスのアライメントなどについてお考えの場合は、動的割り当てをアライメントする方法は内部環境/ libc の問題です。サイズがアラインされている場合、一部の配列が特定の方法でアラインされているとは限りません。多くのアロケーターは、ある値 (機械語の約 2 倍または 4 倍のサイズ) にアラインされたメモリ ブロックを返すため、アラインメントを気にする必要はありません。
重要な可能性があるいくつかのことだけを覚えています。
配列を処理するためにベクトル演算やアンロールされたループを使用したい場合があるため、割り当てられた領域を超えないようにプログラムを作成するためにパディングが必要になる場合があります。(ただし、ベクトル エンジンが標準の C 実装が提供する以上のアライメントを必要とする場合は、単純な malloc() 以外の方法でメモリを割り当てる必要があります)。
ほとんどのメモリ アロケータは、割り当てられた領域の横にサービス情報 (たとえば、割り当てられたブロック サイズ) を格納し、解放されたメモリの合計サイズはわずかに大きくなります。いくつかのラウンド値よりもわずかに小さいサイズの領域を割り当てて、領域を標準的な割り当てブロック (メモリ ページなど) に密集させるのが最善の場合があります。例として、CPU に 4k ページがある場合、ページには 3 1024 バイト ブロックのみが含まれる可能性がありますが、4 1008 バイト (=1024-8) ブロックが含まれる場合があります。
また、多くのメモリ アロケータにはブロック サイズのしきい値があり、そのようなメモリ未満はヒープから割り当てられますが、それを超えるメモリはハードウェア ページ全体によって OS VM ディスパッチャーから直接取得されるため、ページ境界に配置されます。この場合、ページ全体を取得するには、割り当てサイズをページ サイズに丸める必要がある場合があります。
他にも問題があるかもしれませんが、覚えていません。
配列をヒープに動的に割り当てていると仮定すると、malloc の内部割り当てアルゴリズムが実際のメモリ要求からカーネルへの抽象化を行っていると仮定するのが妥当です。つまり、malloc() 呼び出しと libc の brk() (または mmap()) システム呼び出しの間に直接的な関係がある場合とない場合があります。
malloc の man ページには、これに関する詳細が記載されています。
したがって、メモリ使用量に関しては、8 バイトの倍数で割り当てるかどうかは実際には問題にならないことを示唆する傾向があります。これは、malloc が別の (そして賢明な) 何かを実行している可能性が高いためです。
プログラムのパフォーマンスに関しては、メモリ内のデータ構造の割り当てがキャッシュのパフォーマンスに大きな影響を与える可能性があります。ただし、最終的には、アプリケーションのプロファイルを作成して、キャッシュ パフォーマンスを改善できるかどうかを確認する必要があります。コードを書くときにこれを最適化できるようにする厳格な規則があるとは思いません。
メモリと Linux についてさらに学びたい場合は、Ulrich Drepper が数年前に LWN 向けに素晴らしいシリーズを書いています。