C# Доступ к массиву и доступ к указателю C ++ PInvoke - PullRequest
1 голос
/ 05 мая 2020

У меня есть идея оптимизировать большой массив с зазубринами. Скажем, я попал в массив c#

struct BlockData
{
    internal short type;
    internal short health;
    internal short x;
    internal short y;
    internal short z;
    internal byte connection;
}
BlockData[][][] blocks = null;
byte[] GetBlockTypes() 
{
   if (blocks == null)
      blocks = InitializeJaggedArray<BlockData[][][]>(256, 64, 256);
//BlockData is struct
MemoryStream stream = new MemoryStream();
for (int x = 0; x < blocks.Length; x++)
{
    for (int y = 0; y < blocks[x].Length; y++)
    {
       for (int z = 0; z < block[x][y].Length; z++)
       {
           stream.WriteByte(blocks[x][y][z].type);
       }
    }
}
return stream.ToArray();
}

Сохранение блоков как BlockData*** в C ++ Dll, а затем использование PInvoke для их чтения / записи будет более эффективным, чем их хранение в массивах C# ?

Примечание. Я не могу провести тесты прямо сейчас, потому что мой компьютер сейчас находится в эксплуатации.

Ответы [ 3 ]

1 голос
/ 05 мая 2020
• 1000 в сценарии реального времени. И. NET - неправильный выбор для сценария ios реального времени с самого начала. Если вы работаете в сценарии реального времени, это не будет единственной вещью, которую вам придется избавиться от G C Управление памятью и проверки безопасности.

Это правда, что доступ к массиву в Native C ++ выполняется быстрее затем доступ к нему. NET. . NET имеет индексаторы как правильные вызовы функций, аналогично свойствам. И. NET действительно проверяет в Индексе, действительно ли. Однако все не так плохо, как вы думаете. Оптимизация довольно хорошая. Вызовы функций могут быть встроены. Если возможно, доступ к массиву будет сокращен с использованием временной переменной. И даже проверка массива не спасает от толкового удаления. Так что это не такое большое преимущество, как вы могли подумать.

Как отмечали другие, P / Invoke потребляет любые выгоды, которые могут быть, с его накладными расходами. Но на самом деле переход в другую среду не нужен:

Дело в том, что вы также можете использовать голые указатели в. NET. Вы должны включить его с помощью небезопасного кода, но он есть. Затем вы можете получить кусок неуправляемой памяти и рассматривать его как массив в собственном C ++. Конечно, это может привести к ошибкам, таким как неправильная арифметика указателя c или переполнение - точные причины эти проверки существуют в первую очередь!

1 голос
/ 05 мая 2020

Будет ли хранение блоков как BlockData *** в C ++ Dll и последующее использование PInvoke для их чтения / записи более эффективным, чем их хранение в C# массивах?

Нет, потому что P / Invoke имеет значительные накладные расходы , тогда как доступ к массиву в C#. NET компилируется во время выполнения JIT в довольно эффективный код с проверками границ. Зубчатые массивы в. NET также имеют адекватную производительность ( единственное слабое место в. NET - это настоящие многомерные массивы , что разочаровывает - но я не верю, что ваше предложение поможет этому либо ).

Обновление: Производительность многомерного массива в . NET Core на самом деле кажется хуже , чем. NET Framework (если я читаю это правильно заправить) .

0 голосов
/ 05 мая 2020

Другой способ взглянуть на это - G C и общее обслуживание. Ваше предложение по сути такое же, как выделение одного большого массива и использование (layer * layerSize + row * rowSize + column) для его индексации. PInvoke даст вам следующие недостатки:

  • вы, вероятно, закончите с неуправляемым распределением для массива. Из-за этого G C не знает о большом количестве выделенной памяти, и вам необходимо обязательно уведомить об этом G C.
  • PInvoked-вызовы не могут быть полностью встроены, в отличие от всех. Net код во время JIT
  • вам необходимо поддерживать код на двух языках
  • PInvoke не такой переносимый - требует, чтобы библиотеки c определяли платформу / битность, и добавляли много веселья при совместном использовании вашей программы.

и один возможный выигрыш:

  • удаление граничных проверок, выполняемых. Net на массивах

Назад Расчет салфетки показывает, что в лучшем случае оба будут сбалансированы в сырой производительности. Я бы go с. Net -только версией, так как ее проще поддерживать, меньше удовольствия с G C.

Кроме того, когда вы скрываете автогенерацию / частично сгенерированные фрагменты за методом индекса фрагмента легче писать код на одном языке ... На самом деле тот факт, что полностью заполненные фрагменты очень потребляют память, ваша основная проблема, вероятно, будет связана с использованием памяти / памяти доступ затрат, а не чистой производительности перебора элементов. Попробуй измерить ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...