■5779 / inTopicNo.2) |
Re[1]: ユーザ定義構造体配列のマーシャリング |
□投稿者/ mあ (30回)-(2007/07/23(Mon) 15:47:14)
|
■No5767 (BBlue さん) に返信 > ユーザ定義構造体配列をアンマネージドメモリへ転送、 > また、アンマネージドメモリから構造体配列へ復元する方法は、 > Win32APIのCopyMemoryを使用する以外ないのでしょうか。 > API呼び出しがべたでしっくりきません。他によい方法はないでしょうか? > ビデオカードへ頂点バッファをコピーする処理なため、パフォーマンスを優先させたいです。
ベタベタなのは変わりませんが、自分でコンパイルする分だけ速度改善される と考えます。 下の方の参考資料に、最適化が掛かると普通に MOVSD で展開される、とあるので 工夫すれば、C++オンリーでアセンブラと遜色ないコードが書けるかと思います。 ライブラリの CopyMemory は、汎用ですので、入力が何なのか分からないので バイト単位のコピー(MOVSB) ですが。
public void extern MyCopyMemory(DWORD *srcEAX, DWORD *dstEBX, int size4nECX); size4nECX = (sizeof(structureX) * N / sizeof(int)) if (size4nECX & 3) size4nECX++; です。4n整合
push ESI,EDI,DS,ES MOV ESI, srcEAX ;16 バイト整合しておくと速いかも MOV EDI, dstEBX ;おなじく mov ES, DS ;;mov ECX, ECX REP MOVSD pop ES,DS,EDI,ESI
大昔のまんまなら、EAX,EBX,ECX,EDX,ESI,EDI は汎用なので保存の必要無し ただ、ESI,EDI ともワード整合以下だと、ペナルティが発生するので少し遅 くなります。大昔、80486 ハンドブックで見た記憶があります。
MOVSB/W/D は、命令1回で、DI=SI & SI+=4,DI=+=4 を行います(MOVSD の時)。 REP は、CX を デクリメントして 0 では無い間ループしなさい、って意味の 命令接頭語です。
スタック経由なら、 [ret addr] push ebp mov ebp, esp pushf mov esi, 4[ebp] mov edi, 8[ebp] mov ecx, 12[ebp] cld rep movsd popf pop ebp
マネージド・アンマネージドコードで構造体の持ち方が同じな場合に限ります。
でも、CopyMemory も、REPZ MOVSB だから、4倍速度が違うだけですからね。 末端処理や境界整合の問題があるので、4バイト一括転送が使われるケースは 稀なんじゃないかな。
C++で組んで、C# からインポートして使う、という感じになります。 src , dst 共、境界整合用に若干余分なバイト数を(3バイト以下)転送して しまう可能性があるので、それらを考慮するなら、構造体はきっちり4n で 割り切れる(パディング含めて)大きさにするか、1つ余分に取っておくと 良いかもしれませんね。最悪実行中に未割り当て領域侵害でドカーンって いっちゃうかもしれません。
http://www5c.biglobe.ne.jp/~ecb/assembler/7_2.html STRING 命令云々
http://www.cyborg.ne.jp/~xelf/developer/MemoryCopy.html MMX 命令が最速?MMXはわかりません。m(__)m
http://hp.vector.co.jp/authors/VA014520/asmhsp/chap7a.html
|
|