アラインメントのサイズ

受付中

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 2,009

strike1217

score 578

構造体のアラインメントについては過去に質問したので、今回は別の話です。

リンク内容

4バイト整数または4バイト浮動小数をメモリに格納する場合, 先頭アドレスが4の倍数になるようにすれば上図の1ワードに収まるため, 1回のメモリアクセスで読み書きできる. このようにデータの先頭アドレスを4の倍数にすることを, 「4バイト境界にアライン (align:整列,位置合わせ) する」という.

64bitシステムだと8Bなので、8の倍数にすれば美しくなるんですかね。

char buf[a];  // aが8の倍数


ところがアセンブリ言語を見ると64bitでもスタックは32bitです。
つまり64bitでもアラインメントは4の倍数にしなくてはダメという事ですよね?
このサイトの説明が変なのでしょうか?
8B? 4B?

私の本の中にこう書いてあります。

malloc() calloc() realloc()により割り当てたメモリについては、C言語すべての標準の型を正しくアラインメントするようにPOSIXでも定義されています。Linuxでも上記ライブラリ関数は、32bitシステムは8バイト境界に、64bitシステムでは16バイトにアラインメントします。

ヒープ領域はスタックとは別物なのでアラインメントも異なるという事ですかね。
各領域ごとにアライメントが決められているんでしょうか??

1回のメモリアクセスで読み書きできる. このようにデータの先頭アドレスを4の倍数にすること

この説明では全く分かりません。
CPUによって固定ならどんな領域でも64bitなら8Bにしなくてはならないはずです。

さらに謎な点が・・・
アライメントはそのシステムのアーキテクチャによって固定ですよね?

#define _XOPEN_SOURCE 600
#define GNU_SOURCE

#include<stdlib.h>

int posix_memalign(void **memptr, size_t alignment, size_t size);


任意のサイズでアラインメントを可能にする関数ですが、任意のアライメントってどういうことですか??

Linux 64bit x86_64です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

アライメントはそのシステムのアーキテクチャによって固定ですよね?

いえ、状況によってアラインメントは異なります

マシン内では、整数のアライメントはふつう、整数自体の長さ以下となります(そうでないと、整数配列に隙間が空いて、効率が悪くなります)。32ビット整数なら4バイト境界、64ビット整数なら8ビット境界、SSEで使うような128ビット整数は16バイト境界というようになることもあります。もちろん、1バイトのchar好きな場所に置けます

malloc()のアライメントは、大きな型の変数を入れても問題ないように、大きなアライメントを取るようになっています…が、SSEなどアセンブラで特殊な型を触る場合にはそれでも合わないので、手動調整が必要になる場合もあります。

「アライメントを手動で調整する機能」は、基本的に「バイナリデータが特定のアライメントで決め打ちになっているような場合」に使うもので、処理中にずらすようなことはあまり行いません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/25 14:47

    アライメントは変数によっても異なり、領域によっても異なるという事ですかね??

    キャンセル

  • 2017/09/25 14:53 編集

    mallocの場合の扱いは、「領域の違い」というより「何が入るかわからないから、大きめに取っている」という話です(16バイト境界に揃えておけば、8バイト・4バイトなどのアラインとして使っても全く問題ないので、「大は小を兼ねる」ということです)。

    キャンセル

  • 2017/09/25 14:59

    あ、なるほど!ヒープの場合はそういう考え方なんですね!

    キャンセル

+2

質問文から察するに、「アラインメント要件」と「(実際の)アラインメント」を混同されているようです。

  • アラインメント要件:CPUアーキテクチャにおいて、型(type)毎に 最低限満たすべき アラインメントが決められています。例:char型では1int型では4double型では8など。
  • (実際の)アラインメント:プログラム実行時に決まる、変数や動的確保メモリのアドレス値。例:malloc()関数が確保するメモリ領域のアライメントは8など。

(実際の)アライメントは、アライメント要件を満たす必要があります。mallocが返したアドレス値のアラインメントが8であれば、それより 小さいアライメント要件を持つ 型(type)を安全に格納できます。maisumakunさん回答にある「大は小を兼ねる」のイメージが分かりやすいかと思います。


各領域ごとにアライメントが決められているんでしょうか??

(実際の)アライメントは、コンパイル(静的リンク)およびプログラムロード(動的リンク)に決定されます。つまり、プログラムがメモリ上にロードされるときまでに最終決定されるものです。

アライメントはそのシステムのアーキテクチャによって固定ですよね?

「アライメント要件」はアーキテクチャで決まります。

任意のアライメントってどういうことですか?

前述の説明通りです。C言語の仕様により、「動的確保されるメモリアドレスには、任意の型を配置できること」が保証されています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/27 00:27

    > https://teratail.com/questions/37555
    > 「32bit CPUなら4バイト境界、64bit CPUなら8バイト境界が多いです。 」
    こっちの方の発言も、文脈から「double型のアラインメント」の話であって、アラインメント全般の話じゃないですね。(その前にshort型のアラインメントが2という話も出てきますし。)

    それに、「境界をどこに調整するかは処理系(主にCPUの都合)によって異なり、32bit CPUなら4バイト境界、64bit CPUなら8バイト境界が『多い』です。」 と言っているのであって、CPUが64bitなら『必ず』8バイト境界なんて言ってないですよ。

    キャンセル

  • 2017/09/27 00:42

    ふむー。だんだんわかってきました。

    キャンセル

  • 2017/09/28 13:15

    アライメントがずれてても遅い(一つのデータを取得するのにデータバスを2回使う)だけで動くには動く、ってCPUもありますね。

    キャンセル

+1

「アライメントとは?」については皆さんの回答と議論がすでにあるので、
posix_memalign()についてだけ。

posix_memalign() は通常用途ではなく、ハードに依存してて例えば1024バイトきざみのアドレスでないとうまく動作しない、あるいはその方が速くなる、というような条件がある場合に利用します。

通常のアプリケーションでも本来は意識しなければならないデータバスの問題とかであれば、コンパイラとライブラリがアーキテクチャ(x64など)を理解しているのでmalloc()で良いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/30 00:03

    う~~~ん。
    大きなアライメントが必要になる場面がいまいちよくわからないんですよね。

    キャンセル

  • 2017/10/02 14:53

    ぱっと思いつくのは、sysconf()やmlock()あたりと組み合わせて、ページ境界に合わせてメモリ確保&ページロックしちゃうようなコードを書きたいときとか。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る