2016-07-19 8 views
0

私は最適化したい64ビットアセンブリを作成していますが、データを渡すための「適切な方法」ネイティブコードに変換されます。複雑な.NETデータをネイティブ(アセンブリコード)に渡す

データが.net側で生成されるため、asm側でデータを割り当てることはオプションではありません。

それは契約ブレーカませんが、直接.NET =>ネイティブDLLソリューションがある場合、私はむしろC++/CLIを避けるだろう

私が渡したいデータはで返されるものと同様の形式でありますこのクエリ:

var q = Enumerable.Range(bla) 
    .Where(bla) 
    .Select(item=>very complex and cpu intensive query and subqueries) 
    .Select(item=> new 
    { 
     a=item.a, 
     b=item.b, 
     c=item.c, 
     d=item.d, 
     e=item.e, 
     f=item.f 
    }).ToArray(); 

これを最初にコピーすることなくネイティブコードに渡す方法はありますか?私が見つけたのは、2つの欠点を持つ解決策でした。

1)データをコピーする必要があります(それはRAMの使用量を考慮すると安価な操作ではなく、100GB以上のRAMを使用しています。 !) 2)現在、私はこのようhavelooks多分これは、非匿名の種類とstructlayoutsを軽減することができた(データを平坦化)

必要です:

var array = Enumerable.Range(bla) 
    .Where(bla) 
    .Select(item=>very complex and cpu intensive query and subqueries) 
    .SelectMany(item=> new int[] 
    { 
     item.a, 
     item.b, 
     item.c, 
     item.d, 
     item.e, 
     item.f 
    }).ToArray(); 

     int size = Marshal.SizeOf(array[0]) * array.Length; 
     IntPtr ptr = Marshal.AllocHGlobal(size); 
     Marshal.Copy(array, 0, ptr, array.Length); 

ことを取り除くために方法はありますか?追加の割り当てと多くのRAMを節約できますか?私は本当にパフォーマンスとメモリ使用の理由の両方のために、実際のメモリとコピーではなく、使用することが大好きです。

残りのコードをアセンブリに移植することは、あまりにも複雑で、CPUが集中する間はボトルネックではありません。

+0

今やギザギザの配列があります。 * struct *を宣言すると、より効率的になります。しかし、100ギガバイトはあまりにも多く、それは適合しません。実際には、今のところフィットしません。そのギザギザの配列は、それほど多くの要素を持つことはできません。だから多分あなたの要件は想像されており、実用的な考慮に基づいていません。 –

+0

@HansPassant私はギザギザの配列を持っていない、それはselectmanyによって平坦化されている、それはフラットな配列です、またはあなたが何を言っているのを忘れていますか? –

答えて

1

GCHandle.Alloc()を使用して配列を固定することができます。それが管理されたデータのコピーを避けるための標準的な方法です。

これにはデータをblittableにする必要がありますが、blittableでない場合は、どのような場合でもアセンブリコードからデータを操作する機会はありません。

+0

「blittable」とは何を意味し、どうすればそのことを保証できますか?コピーなしでアンマネージメモリにポインタを渡すことができるのであれば、解決策になるかもしれません。 –

+0

ウェブ検索でその質問に答えます。私はあなたのためにそれをすることができますが、私はあなたが管理できると確信しています。 –

+0

確かに、データが質問の一部であったように、回答の一部にすべきであるように思われたので、答えを簡略化するのに十分なコンテキストがあると仮定しました(回答からltを削除します)か、代わりに)どんな場合でも私はそれを見ていただきありがとう:) –

関連する問題