お世話になります、Air です。
C# でのアライメントのとり方について質問です。
算術系のクラス等を自作した場合
計算に SIMD 等を使っているとどうしても
クラスを16バイトアライメント等で確保しなくてはならない
場合が出てきます。
C++ の時は 15バイトほど多めにとってみたいな風にしていたのですが
C# の場合はどのようにすればよろしいのでしょうか?
ご教示よろしくお願いします。
・開発環境
WindowsXP
Visual Studio .NET2003
StructLayout属性のPackフィールドで設定できます。
レスありがとうございます。
これは Pack = 16 ということでしょうか?
ちなみに、float 型の変数を4つ持ったクラスを宣言する際
Pack = 16 としてしまうと、クラスの大きさは64バイト
みたいになってしまったりしますよね?
> ちなみに、float 型の変数を4つ持ったクラスを宣言する際
> Pack = 16 としてしまうと、クラスの大きさは64バイト
> みたいになってしまったりしますよね?
試してみましたか?
---- コード ----
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test
{
public float f1;
public float f2;
public float f3;
public float f4;
}
class Class1
{
static void Main ()
{
Console.WriteLine(Marshal.SizeOf(typeof(Test)));
}
}
---- 結果 @ Visual C#.NET 2003 ----
16
まぁ,所詮はアンマネージコードの世界だけでの話ですが……。
し、失礼いたしました。
ネットで得た知識のみで発言していました、すいません。
たしかにおっしゃられる通りの結果でした。
ちなみに、他にも試してみたのですが
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test00
{
public float f1;
public float f2;
public short s1;
public short s2;
}
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test01
{
public short s1;
public short s2;
public float f1;
public float f2;
}
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test02
{
public float f1;
public float f2;
public float f3;
public short s1;
}
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test03
{
public short s1;
public float f1;
public float f2;
public float f3;
}
Test00 と Test01 のサイズは12と出ました。
これは大いに納得です。
ですが、Test02 と Test03 は共にサイズは16と出ました。
float 3つに short 1つだから14じゃないの?と思うのですが・・・
ちなみに
[StructLayout(LayoutKind.Sequential, Pack=16)]
struct Test04
{
public float f1;
public short s1;
public float f2;
public short s2;
}
このパターンもサイズは16と出ました。
何か私が根本的に勘違いでもしてるのでしょうか?
おわかりになる方、説明していただけませんでしょうか?
よろしくお願いします。
あんまりC#でアラインなんて考える必要ないのですが……。
# そもそも,マネージコード中での構造体の配置は完全には決まっていないはず。
> ですが、Test02 と Test03 は共にサイズは16と出ました。
> float 3つに short 1つだから14じゃないの?と思うのですが・・・
Test02やTest03のマーシャリングした結果のサイズが14バイトだと,
アンマネージな配列を作った時に,
・1個目の要素は4の倍数のアドレスに置かれる
・2個目の要素は4の倍数+2のアドレスに置かれる
というような状況が発生してしまいます。
これだとfloat要素が4の倍数のアドレスに置かれなくなるため,
良くない状況が発生してしまいます。
基本的に,各要素のアラインは,
要素のサイズと指定されたアラインの小さい方の値になります。
そして,オブジェクトのサイズは最大のアラインの値の倍数になります。
> このパターンもサイズは16と出ました。
+00 : f1 <align:4>
+04 : s1 <align:2>
+08 : f2 <align:4>
+0C : s2 <align:2>
と配置され,全体のアラインは4ですから,
14以上で最小の4の倍数である16が,
Test04のアンマネージへマーシャリングされた時のサイズになります。
# あぁ,どこがC#の話なんだか……。
なるほど!おおいに納得しました。
ていうか、アライメントとかをそこまで気にするようなプログラムなら
おとなしくC++で書けよってとこですかね。
丁寧なご説明ありがとうございました。