トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
C++
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索

___

■ Alignment(境界配列)




  DESC
    データ型のサイズにより、2, 4, 8の倍数のアドレスに配置されること
    ハードウェア的な制約もあれば
    より高速な処理をするためにコンパイラ(リンカ、ローダ)が指示するものもある。

    メモリ、CPU 間でやりとりできるデータのサイズは 16bit, 32bit だったりする
    整列しておけば 4byte のデータを 1回で転送できる

  Alignment をする理由
     memory < -> CPU 間での data 転送が 4byte 単位のため整列した方が一度の転送ですむ
     最新のプロセッサの命令によっては 16 byte アラインメントにある必要がある。
     キャッシュラインにそろえることで、キャッシュミスを防ぐ。
POINT 変数は宣言順に確保されるとは限らない ローカル変数は宣言した順に, 配置されない 構造体の各メンバは宣言順だが, Alignment されて、メンバの間には隙間( padding ) が空く場合もある 構造体のサイズが padding されるのは, 各メンバが適切な位置に配置されるため隙間が空いてしまう。 隙間が空くのを防ぐにはメンバの構成を入れ替える。 または padding を明示しておく。
    BAD
    struct Foo {
      int    i0;
      short  s0;
      int    i1;   // int 型は 4 の倍数で配置されるため s0, i1 の間に隙間が空いてしまう。
      short  s1;
    };

    // OK
    struct Foo {
      int    i0;
      int    i1;
      short  s0;
      short  s1;
    };

    // OK
    struct Foo {
      int      i0;
      short    s0;
      char pad[2];
      int      i1;
      short    s1;
    };
Compiler の指定 で 変更可能( vc: 構造体 mem への alignment ) -> mem , cpu は 32 本の線で結合 -> 可変サイズで, Buffer をもつより, Alignment を守って大きめのサイズにした方が都合がよい場合もある.
    // sizeof(S) = 2
    //    2 コ で 4 byte
    struct S{
      short s;
    };

    // sizeof(C) = 1
    //    4 コ で 4 byte
    struct C{
      char c;
    };

    // sizeof(S3) = 6
    struct S3{
      short s0;
      short s1;
      short s2;
    };
x86 系では, double は 8ByteAlignment にすると効率がよい。 Architecture によっては必須になる. Alignemnt をそろえた, memory の取り方
     data = (void *)myMalloc( size + 32 );     // 32 byte Alignemnt

     s_data_org = data;                         // ori 保存

     data = (void*)(((u_int)data + 31) & ~31 ); // Alignemnt Macro
POINT struct cls mem 内が連続しているとは限らない 現実問題として, float, short, char, が struct 内に並ぶ場合は 連続して配置されている enum も連続していると考えられる // 12 byte struct Foo{ char c0; // 1 の倍数で alignment 1 float f0; // 4 の倍数で alignment char c1; // 1 の倍数で alignment };
                                    // 残り3byteを埋めないと次の構造体を配置した場合にf0の配置に問題がおきる。
    [c0][  ][  ][  ][f0][f0][f0][f0][c1][  ][  ][  ]
// sizeof(Foo) = 8 FILE: main.cpp struct Foo{ char c1; char c2; float f; };
___

■ プラグマでアラインメントを指定する

SYNTAX __declspec( align( # ) ) declarator コンパイラのプラグマでアラインメントを指定する。 VisualStudio では以下の方法で指定する。
    // Vector 構造体を 8 byte の境界の配置するように指示する
    __declspec( align(8) ) struct Vector
    {
      short x;
      short y;
      short z;
    };

    typedef struct ALIGN(8) { short vx, vy, vz, pad; } SHORT_VECTOR;
アラインメントを指定すると, アドレスが 8 byte の境界にあることがわかる。
    Vector v;

    int adr = (int)&v;
    adr %= 8;

    printf( "addr %d  %d", &v, adr );
POINT alignment の指定は 2 冪でないとだめ
    ERROR C2344: align(12) : アライメントは 2 の累乗でなければなりません。
    __declspec( align(12) ) struct SA
___

■ キャッシュライン(CacheLine)

よく使うデータはキャッシュラインに揃えることで、キャッシュミスが置きにくくなりプログラムの速度があがる。 cacheは、16bytesごとの塊xN個で構成されている。 この16bytesの塊1つを、1lineという。 lineが何個あるかは、cacheサイズをlineサイズで割れば計算できる。 1KB / 16 = 64なので、このcacheには64line存在する POINT 良く使うデータや、連続して使うデータが同じcache lineに割り当てられてしまうと、cache missが頻発してしまいます。
___

■ アラインメントを指定しない場合

Object はまず固有のサイズに対するアラインメントをもつ。 int は 4byte 境界に、 double は 8byte 境界に配置される。 int は 4 で割り切れる場所にないといけない。 クラス内にあるメンバオブジェクトは、オブジェクトのアラインメントのうち最小の値の位置にアラインメントされる。
    struct Test {
      char  c;
      short s;  // 2byte 境界にアラインメントするため, c と s 間に 1byte のパディングがはいる

    };



2. (push 8) は 1 の alignment の設定と比較してより小さい alignment が優先される 3. -> 適当に詰め物をする
  // 4 Byte 境界に押し込め と命令
  #pragma pack(push, 4) -> 12 byte
  struct Foo
  {
    char B;     // 1 byte alignment
    double W;   // 4 byte alignment( 8 より優先 )
    char H;     // 1 byte alignment
    short s;    // 2 byte alignment
  };

#pragma pack(pop) POINT プリミティブな値は、min( szObj, Alignment )の倍数のアドレスに配置する 一回で CPU に data を渡せるように箱に詰め物をするのが Alignment 構造体は 2冪サイズにするべき ( 最低でもキャッシュライン倍数にする )

NINJAIDX 12