UnmanagedDoubleArray on C#
C#でポインタを使う実験としてdouble型の配列を作ってみた。ほかにもbyteのも作ったけれど、ほとんど同じなので省略。
unsafe class UnmanagedDoubleArray : IDisposable { double* ptr; public readonly int Length; static readonly double* ZeroPtrDouble = (double*)IntPtr.Zero; const int Size = sizeof(double); public UnmanagedDoubleArray(int Length) { this.Length = Length; this.ptr = (double*)Marshal.AllocCoTaskMem(Length * Size); } public double this[int i] { get { return this.ptr[i]; } set { this.ptr[i] = value; } } public void Dispose() { if (this.ptr != ZeroPtrDouble) { Marshal.FreeCoTaskMem((IntPtr)ptr); this.ptr = ZeroPtrDouble; } } ~UnmanagedDoubleArray() { this.Dispose(); } }
が…期待したほど早くならない。classなんぞ作らないで直に書いたとしてもあまり速くならない。
確かに、メモリ領域を確保する部分についてはこちらのほうが断然早い。なぜなら初期化をしないからだ。つまりデータをすべて0で書き込むということをしない。
しかし、読み出し書き出しは配列でも十分最適化されていて大差ない。というか大差ないどころか下手するとこっちのほうが遅い…(直の場合でもね)
ちなみにMarshal.ReAllocCoTaskMemというメソッドを使えば確保した領域を広げられるみたいだが、使ってみたら元の値が微妙に書き換えられてしまうことがあった…なぜ??
昔、Win32APIをDllImportしてメモリクリーナを作ったけれど、MarshalクラスにWrapされてたのね…
これ使えばLinuxでもメモリクリーニングしてくれるのかも
ジェネリクスつかって書けよといわれそうだが、Managedな構造体はポインタを作れませんて言われた…きっとインスタンスによって大きさがまちまちだからかもしれない。大きさが一定のものだけに型制約とかできないのかなー