Арифметика большого массива в С#

Каков наилучший способ хранения 2D-массива в С# для оптимизации производительности при выполнении множества арифметических элементов в массиве?

У нас есть большие (около 1,5 Гб) массивы, которые, например, мы хотим умножить друг на друга по элементу. Производительность имеет решающее значение. Контекст, в котором это делается, находится в С#. Есть ли какой-либо умный способ хранения массивов и итерации по ним? Можем ли мы написать эти части в неуправляемом С++, и это действительно увеличит производительность? Массивы должны быть доступны для остальной части программы С#.

В настоящее время (в c) массив хранится как один длинный вектор. Мы выполняем вычисления для каждого элемента массива и перезаписываем старое значение. Вычисления обычно уникальны для каждого элемента вектора.

Временные эксперименты показывают, что сохранение и повторение данных в виде массива в С# происходит медленнее, чем сохранение его как 2D-массива. Я хотел бы знать, есть ли еще лучший способ обработки данных. Конкретная выполняемая арифметика не имеет отношения к вопросу.

Ответ 1

Анна

Вот отличная страница, в которой обсуждается разница в производительности между традиционными языками научного программирования (fortran, С++) и С#.

http://msdn.microsoft.com/en-us/magazine/cc163995.aspx

Согласно статье С#, при использовании прямоугольных массивов (2d) может быть очень хорошим исполнителем. Ниже приведен график, показывающий разницу в производительности между массивами массивов (массивов массивов) и массивами прямоугольных массивов (многомерных).

alt text http://i.msdn.microsoft.com/cc163995.fig08.gif

Я бы предложил экспериментировать и использовать анализ производительности в VS 2008 для сравнения.

Если использование С# "достаточно быстро", ваше приложение будет намного проще в обслуживании.

Удачи!

Ответ 2

Для лучшей производительности массива убедитесь, что вы используете массив с одним размером с более низким индексом 0.

Чтобы получить доступ к элементам массива как можно быстрее, вы можете использовать небезопасные указатели, например:

int[] array = Enumerable.Range(0, 1000).ToArray();

int count = 0;
unsafe {
    fixed (int* pArray = array) {
        for (int i = 0; i < array.Length; i++) {
            count += *(pArray + i);
        }
    }
}

EDIT Drat! Не заметил, что вы сказали 2D-массив. Этот трюк не будет работать с многомерным массивом, поэтому я не уверен, насколько он поможет. Хотя вы можете превратить любой массив в одномерный массив, выполнив некоторую арифметику в индексе массива. Просто зависит от того, интересует ли вас производительность при индексировании массива или в итерации по массиву.

Ответ 3

Если вы загружаете F # и ссылаетесь на одну из библиотек времени исполнения (я думаю, это FSharp.PowerPack) и используйте Microsoft.FSharp.Maths.Matrix. Он оптимизирует себя в зависимости от того, используете ли вы плотную или разреженную матрицу.

Ответ 4

Вы повторяете матрицу по строке или по столбцу или и тому и другому? Вы всегда получаете доступ к близлежащим элементам или произвольно получаете доступ к матрице.

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

Довольно простой способ сделать это - написать небольшую функцию доступа, чтобы превратить индексы строки /colum в индекс и работать над одномерной матрицей, способом кэширования.

Функция должна группировать соседние координаты в соседние индексы. Меморандум может использоваться, если вы работаете на мощности двух размеров. Для размеров без питания вы можете часто вводить только самые низкие 4 бита в порядок миномов и использовать обычную индексную арифметику для верхних бит. Вы по-прежнему будете получать значительное ускорение, даже если преобразование координат для индексации выглядит дорогостоящим.

http://en.wikipedia.org/wiki/Z-order_(curve) < - Извините, не могу связать, что SO не любит URL с тире в нем. Вы должны отказаться от пасты.

Ускорение фактора 10 и более реалистично. Это зависит от алгоритма, который вы используете над вашими матрицами.