LoginSignup
10
9

More than 5 years have passed since last update.

C++でアライメントを意識したので覚書

Last updated at Posted at 2017-01-13

はじめに

初めてC++に触れてから約4年。
恥ずかしながら初めてアライメントを意識したので、覚書としてまとめておきます。

なぜ意識したか

八分木による空間分割を実装していた時の話です。
静的に分割を行うと常時 空間数(約240k)*クラスサイズB のメモリが必要になりました。
そのためクラスサイズを落とせないか考えるうちに、意識した次第です。

アライメントとは

記憶装置にデータを書き込む際、書き込むデータの大きさや先頭の位置(アドレス)を、装置の管理単位の整数倍になるように調節すること。例えば、4バイト単位でメインメモリを管理してるコンピュータで、メモリ上に置くデータの先頭アドレスが4の倍数になるように調節する。こうすることで、装置がデータの読み書きを効率良く行うことができるようになり、処理効率の向上が見込める。※1

だそうです。
これを意識しないと、無駄な領域を発生させてしまいます。

アライメントを意識しないと

class A // 4B
{
    A* pA;
};

class B // 8B
{
    bool hoge;
    bool foo;
    B* pB;
};

class C // 12B
{
    bool hoge;
    c* pC;
    bool foo;
};

BとCの内容は同じですが,Cにパディングが挿入され4バイト無駄にしています。※2
これが既述の八分木で起きた場合、約10MBもの無駄が発生してしまいます。
これを抑えるために、アライメントを意識してメンバを並べなければいけません。

アライメントを意識する上で必要なこと

パディングが挿入されないように並べるためには、データのサイズを知っておく必要があります。
全ての型のサイズを覚えるのは厳しいので、有名所を書いておきます。
64bitCpu:VisualStudio2015:x86環境で実行しています
・組み込み型

サイズ(バイト)
int 4
unsigned int 4
char 1
unsigned char 1
short 2
unsigned short 2
__int64 8
bool 1
float 4
double 8

・参照
参照のサイズに付いては別の記事で書かれていました。
ポインタのサイズと同等と考えて良さそうです。

・ポインタ
ポインタはx86の場合4バイト、x64の場合8バイトです。

・コンテナ

サイズ(バイト)
list 12
vector 16
deque 20
forward_list 8
map 12
unordered_map 40
unordered_set 40
array 要素サイズ*要素数

デフォルトテンプレート引数を変更しない場合の数値です。

・その他

サイズ(バイト)
string 28
shared_ptr 8
function 40
system_clock 1
thread 8
mutex 48
type_index 4

まとめ

数バイトですが無駄な領域です。
プロジェクト全体となれば結構な量になるはずです。
細かいことですが、気にかけてみては如何でしょうか?

註釈

※1 知的快楽主義者の備忘録 Wiki様
http://wikiwiki.jp/takemaster/?IT%CD%D1%B8%EC%2F%A5%A2%A5%E9%A5%A4%A5%E1%A5%F3%A5%C8%20%A1%DA%20alignment%20%A1%DB%20%A5%A2%A5%E9%A5%A4%A5%F3%A5%E1%A5%F3%A5%C8

※2 64bitCpu、VisualStudio2015でx86環境で実行しています。

今回のプロジェクトはここで公開しています。

10
9
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9