読者です 読者をやめる 読者になる 読者になる

亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

WritableBitmap最終回(暫定) 見せてもらおうか、Nativeの性能とやらを。

WritableBitmapもつらつらやってきましたが、一応コレで最終回としたい感じです。
最後にNativeAccessをやってみましょう。クラスは3つほど作りますよ。

  • C#本体
  • C++/CLIのラッパー(子クラスのメソッドをコールするだけ)
  • C++NativeのCalculator(処理はここが担う)

本当はC++/CLI側に処理を書いても、速度的にそんなに不利にはならないんですが、もうVS2010でC++/CLI使うとかいうマゾいことはできないので・・・。
ほんとにメソッドをコールするだけにしてます。

まず、Native側のクラスはこんな感じ。スタティックでもいいんじゃないのかという塩梅ですが、まぁ許して。

class CWritableBitmapCalc
{
public:
	CWritableBitmapCalc(void);
	~CWritableBitmapCalc(void);
	//配列の先頭ポインタととサイズ、色パラメータを受け取って、配列を埋めるだけの関数
	void CalcWritableBitmap(unsigned int* arrayPtr, int rowSize, int colSize, unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha)
	{
		for (int row = 0; row < rowSize; row++)
		{
			for (int col = 0; col < colSize; col++)
			{
				unsigned int r = (unsigned int)(red * (col + 1) / colSize);
				unsigned int g = (unsigned int)(green * (row + 1) / rowSize);
				unsigned int b = (unsigned int)blue;
				unsigned int a = (unsigned int)alpha;
				*arrayPtr = (r << 16) + (g << 8) + b + (a << 24);
				arrayPtr++;//ポインタを進める
			}
        }
	}
};

ほとんどC#を移してきただけですね。そいで、こいつをコールするだけの関数をCLIで定義しておきます。

	public ref class WritableBitmapCalcWrapper
	{
	private:
		CWritableBitmapCalc* calc;

	public:
		WritableBitmapCalcWrapper()
		{
			calc = new CWritableBitmapCalc();
		}

		~WritableBitmapCalcWrapper()
		{
			delete calc;
		}

		void CalcWritableBitmap(unsigned int* arrayPtr, int rowSize, int colSize, unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha)
		{
			calc->CalcWritableBitmap( arrayPtr, rowSize, colSize, red, green, blue, alpha);
		}
	};
}

(#゚Д゚)<グルーコードってレベルじゃねえぞ、ゴルァ!!

まあまあ、そんなわけで、こいつを使いますと・・・・

    //上記ラッパークラスのインスタンス。
    var wrapper = new WritableBitmapCalcWrapper();
    bitmap.Lock();

    unsafe
    {

        uint* ptrToWb = (uint*)bitmap.BackBuffer;
 
        wrapper.CalcWritableBitmap(ptrToWb, COLS, ROWS,
            redVal, greenVal, blueVal, alphaVal);

    }
    bitmap.AddDirtyRect(new Int32Rect(0, 0, COLS, ROWS));
    bitmap.Unlock();

とまぁ、こんな具合でネイティブに処理を委譲してやりますと。。。

WritePixels: 241
Pointer Access: 99
Native Access: 37


WritePixels: 246
Pointer Access: 115
Native Access: 52


WritePixels: 231
Pointer Access: 86
Native Access: 37


WritePixels: 250
Pointer Access: 86
Native Access: 37


WritePixels: 214
Pointer Access: 85
Native Access: 37


WritePixels: 225
Pointer Access: 86
Native Access: 40


WritePixels: 230
Pointer Access: 85
Native Access: 37


WritePixels: 225
Pointer Access: 86
Native Access: 38

倍以上違いますか、そうですか。最適化をかなり甘くして(Debugビルドです)これですからねぇ。しかもほとんど複雑な計算はやってないし。
やっぱ、こういうメモリアクセス系はNativeはえー、ということになりますです、ハイ。