1. ホーム
  2. c++

[解決済み] メモリーアライメント:alignof / alignasの使い方は?

2023-02-21 13:52:19

質問

私は今、共有メモリを使って仕事をしています。

私は理解することができません alignofalignas .

cppreference は不明瞭です。 alignof は "alignment" を返しますが、 "alignment" とは何でしょうか? 次のブロックのアライメントのために追加するバイト数? パディングのサイズ? スタックオーバーフロー / ブログのエントリも不明です。

誰かわかりやすく説明してください alignofalignas ?

どのように解決するのですか?

アライメントは、値の最初のバイトを格納できるメモリ位置に対する制限です。(プロセッサのパフォーマンスを向上させ、特定のアライメントを持つデータでのみ動作する特定の命令を使用できるようにするために必要で、たとえば、SSE は 16 バイトに、AVX は 32 バイトにアライメントする必要があります)。

16 のアライメントは、16 の倍数のメモリ アドレスが唯一の有効なアドレスであることを意味します。

alignas

は、必要なバイト数にアライメントを強制します。1, 2, 4, 8, 16, 32, 64, 128, ...のように、2の累乗にのみアライメントすることができます。

#include <cstdlib>
#include <iostream>

int main() {
    alignas(16) int a[4];
    alignas(1024) int b[4];
    printf("%p\n", a);
    printf("%p", b);
}

の出力例です。

0xbfa493e0
0xbfa49000  // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2

もう一つのキーワード

alignof

は非常に便利ですが,以下のようなことはできません。

int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error

というのがありますが、これは

assert(alignof(a) == 16);
assert(alignof(b) == 1024);

現実には、これは単純な "%"(モジュラス)操作よりも厳密であることに注意してください。実際、私たちは 1024 バイトにアラインされたものが必然的に 1、2、4、8 バイトにアラインされることを知っています。

 assert(alignof(b) == 32); // fail.

つまり、より正確には、"alignof" は、何かが整列している2の最大累乗を返します。

また、alignofは基本的なデータ型の最小のアライメント要件を事前に知るための良い方法です(おそらく、charsは1、floatは4などを返すでしょう)。

まだ合法です。

alignas(alignof(float)) float SqDistance;

アライメントが16のものは、16の倍数である次の利用可能なアドレスに配置されます。 (最後に使用されたアドレスから暗黙のパディングがあるかもしれません)。