2017-05-12 4 views
0

私は64ビットの値を持つ構造体を持っているとします。もちろん、64ビットシステムでは、高速読み書きのために64ビット境界にその値を揃えたいと考えています。アラインメントの考慮事項と動的割り当て

この構造体がスタックにプッシュされたり、データセクションに格納されている場合、この値が64ビットになるように構造体を整列させることをコンパイラが行うことをお勧めします。

しかし、この構造をmallocや友人から得たメモリにオーバーレイすると、私はそれらが整列を保証しないと信じています。そのため、64ビットの値が整列しない可能性があります。

私自身のアロケータを使用しても、aligned_mallocまたは代替を使用しても、これを適切に処理する方法は不明です。私は、コンパイラが自分の構造をどのようにパックすることを選択したか分かりません。そのため、アラインメントをどうやって確保するか分かりません。

Ofcには、多くの8,16,64,128などがあります。この構造体のビット値はすべての整列要件を満たしたいと考えています。

+2

標準によれば、mallocはプラットフォームとターゲットのすべてのタイプの配置要件を満たすアドレスを記述します。構造体を持っていても、それはすべてのフィールドのアライメントの最大値になります。それも問題ではありません。 –

+2

_私は彼らがアラインメントを保証しないと信じています_ ...なぜ..? – LPs

+0

http://stackoverflow.com/a/28107740/1606345 –

答えて

2

malloc経由でメモリを動的に割り当てると、返されたメモリアドレスがすべてのビルトインタイプのターゲットプラットフォームの最小整列要件を満たすことが保証されます。これは構造体でも機能します。アラインメント要件は再帰的に解釈されるため、構造体のアライメントはそのメンバのいずれかに必要な最大のアライメントです。

実際には、言語標準によって、ターゲットプラットフォームでコードが正しく動作することが保証されています。これはかなり合理的な保証であり、一般的なケースでこれについて心配する必要はありません。

callocmallocの順序と連続呼び出しによって割り当てられた記憶の連続性、及びrealloc機能:(draft)C99言語規格、§7.20.3( "メモリ管理機能")を引用

不特定である。 割り当てが成功した場合に返されるポインタは、任意のオブジェクト型へのポインタに割り当てられるように適切に配置され、そのようなオブジェクトまたは割り当てられた空間内のそのようなオブジェクトの配列にアクセスするために使用されます(領域が明示的に割り当て解除される)。割り当てられたオブジェクトの有効期間は、割り当てから割り当て解除までの範囲です。そのような割り当ての各々は、他のオブジェクトから離れたオブジェクトへのポインタを生成しなければならない。返されたポインタは、割り当てられた領域の先頭(最下位バイトアドレス)を指します。スペースを割り振ることができない場合、ヌルポインターが返されます。要求された領域のサイズがゼロの場合、動作は実装定義である:ヌルポインタが返されるか、または、返されたポインタがオブジェクトへのアクセスに使用されないことを除いて、サイズがゼロ以外の値であるかのような振舞い。あなたが必要とされるよりも厳しい合わせをしたい場合は、アライメントを心配する必要はあり

(強調鉱山)

だけです。たとえば、お使いのプラットフォームは32ビットアライメントでうまく動作するかもしれませんが、をより良く実行してください。と64ビットアラインメントがあります。この場合、言語規格は、32ビットアライメントで十分であるため、64ビットアライメントが動的に割り当てられたメモリに使用されることを保証するものではありません。 64ビットのアライメントが必要な場合は、そのようなアライメントを強制するコンパイラオプションを設定するか、aligned_mallocのようなものを呼び出す必要があります。

実質的にすべての実装は、構造体のフィールドにパディングを追加して、それぞれを整列させたままにします。コンパイラは一般に、ある種の実装固有のオプションを使用してそのように要求しない限り、構造体を "パック"しません。ただし、これはすべてコンパイラに依存しているため、コンパイラのドキュメントを参照して、それが何をするかを確認する必要があります。

人々が最小限に保証されていることを超えてアライメントを心配し始める最も一般的なケースは、特に128ビットのアライメントがパフォーマンスの向上をもたらすx86上のSIMDコードを書くときです。しかし、コンパイラにSIMDコードを生成させる場合は、(ターゲットプラットフォームの正しいオプションを指定していることを前提として)必要なアラインメントをすでに行っている可能性が非常に高いため、特別な操作は必要ありません。特定の命令の生成を強制するために組み込み関数を使用している場合は、__m128のように、適切な配置を確実にするために注釈を付けられた型も使用する必要があります。厳密な規則に揃えたい場合は、おそらく類似の注釈を自分のtypedefに追加することができます。これを達成する方法の詳細については、コンパイラのドキュメントを参照してください。

mallocは、適切に根本的なアライメントを持っている任意のオブジェクトを格納するために並んだメモリを返すことが保証され、それが割り当てられていたメモリの量に合うことができる:例えば、これはthe documentation for Microsoft's C compilerが言いたいこと

です。 A 基本アライメントは、アライメント仕様なしで実装でサポートされている最大アライメント以下のアライメントです。 (Visual C++では、これはdouble、または8バイトに必要な配置です.64ビットプラットフォームをターゲットとするコードでは16バイトです)たとえば、4バイトの割り当ては、 4バイト以下のオブジェクト。また、オーバー整列タイプとして知られている拡張アラインメントを有するタイプを許可++

ビジュアルC。たとえば、__m128__m256のSSEタイプ、および__declspec(align(n))を使用して宣言されたタイプがnであるタイプは、拡張アラインメントを持ちます。拡張アライメントを必要とするオブジェクトに適した境界上のメモリアライメントは、mallocによって保証されていません。オーバーライドタイプのメモリを割り当てるには、_aligned_mallocと関連する関数を使用してください。

+0

ありがとうございます。あなたが言うように、私が必要としていたコードを見直していたとき(私の場合は、キャッシュに合わせる)、この問題に遭遇しました。素晴らしい返答をいただき、ありがとうございます。 – Kay

2

ほとんどすべての標準に違反するメインストリームの外にあるアーキテクチャを使用していない限り、構造体はパックされ、整列され、構造体が正しく整列されると要素が常に正しく整列し、mallocは常にメモリを返しますアーキテクチャ上のデータ型の可能な限り厳密な位置合わせに一致するように配置されます。

関連する問題