2016-07-19 2 views
0

У меня есть кусок кода, который я хочу оптимизировать, и я пишу для него 64-битную сборку, мне интересно, как «правильный способ» передавать мои данные на нативный код будет.Передача сложных данных .NET в native (код сборки)

Поскольку данные генерируются на стороне .net, выделение его на стороне asm не является опцией.

Хотя это не дело выключатель я предпочел бы избежать C++/CLI, если существует прямая .NET => Native решение DLL

Данные я хочу передать в формате, аналогичном тому, что бы быть возвращены этот запрос:

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(); 

Есть ли способ передать это на собственный код без первого его копирования? Все, что я нашел, было решением с двумя недостатками:

1) Требуется копирование данных (и это не дешевая операция с учетом использования плунжера, мы говорим о 100 ГБ оперативной памяти, я бы предпочел не удвоить его !) 2) Требуется уплощение данные (возможно, это может быть облегчены с не типа Anonymous и structlayouts)

в настоящее время, что я havelooks так:

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); 

есть ли способ, чтобы избавиться от дополнительное распределение и сэкономить много барана? Мне очень хотелось бы иметь возможность использовать фактическую память, а не копию как для производительности, так и для использования памяти.

Портирование остальной части кода на сборку - это не выход, это слишком сложно, и хотя это интенсивность процессора, это не узкое место.

+0

Теперь у вас есть зубчатый массив. Это будет намного более эффективным, если вы объявите * struct *. Но 100 jiggabytes слишком много, что не подходит. На самом деле, он не подходит сейчас, что в зубчатом массиве не может быть столько элементов. Поэтому, возможно, ваше требование просто вошло в мысли и не основано на каких-либо практических соображениях. –

+0

@HansPassant У меня нет зубчатого массива, он сплющен selectmany, это плоский массив, или я не понимаю, что вы говорите? –

ответ

1

Вы можете вывести массив, используя GCHandle.Alloc(). Это стандартный способ избежать копирования управляемых данных.

Это потребует, чтобы данные были blittable, но если он не горит, тогда у вас нет шансов работать с ним из кода сборки в любом случае.

+0

Что означает «мягкий» и как я могу убедиться, что это так? Похоже, это может быть решением, если я могу просто передать указатель на неуправляемую память без копирования –

+0

Веб-поиск ответит на этот вопрос. Я мог бы сделать это за вас, но я уверен, что вы справитесь. –

+0

Уверен, но казалось, что это должно быть частью ответа, поскольку данные были частью вопроса, поэтому я предположил, что существует достаточный контекст, чтобы упростить ваш ответ либо к его легкому (и удалить lt из ответа), либо его нет (и предложить альтернатива) в любом случае я посмотрю это спасибо :) –

Смежные вопросы