Сумма двумерного массива в C # / Linq - PullRequest
2 голосов
/ 13 сентября 2011

У меня есть двумерный массив целых чисел.Я хотел бы написать оптимизированный и быстрый код для суммирования всех столбцов двумерного массива.

Есть какие-нибудь мысли, как я мог бы сделать это, используя распараллеливание LINQ / PLINQ / TASK?

Пример:

private int[,] m_indexes = new int[6,4]  { {367, 40, 74, 15},
                                           {535, 226, 74, 15}, 
                                           {368, 313, 74, 15},
                                           {197, 316, 74, 15}, 
                                           {27, 226, 74, 15},
                                           {194, 41, 74, 15} };

Ответы [ 3 ]

5 голосов
/ 13 сентября 2011

Простейшая параллельная реализация:

 int[,] m_indexes = new int[6, 4]  { {367, 40, 74, 15},
                                     {535, 226, 74, 15}, 
                                     {368, 313, 74, 15},
                                     {197, 316, 74, 15}, 
                                     {27, 226, 74, 15},
                                     {194, 41, 74, 15} };
 var columns  = Enumerable.Range(0, 4);
 int[] sums = new int[4];
 Parallel.ForEach(columns, column => {
     int sum = 0;
     for (int i = 0; i < 6; i++) {
         sum += m_indexes[i, column];
     }
            sums[column] = sum;
 });

Этот код, очевидно, может быть "обобщенным" (используйте m_indexes.GetLength(0) и m_indexes.GetLength(1)).

LINQ:

var sums = columns.Select(
    column => {
        int sum = 0;
        for (int i = 0; i < 6; i++) {
            sum += m_indexes[i, column];
         } return sum; 
    }
).ToArray();

Обязательно профилируйте на реальных данных здесь , если вам действительно нужно оптимизировать производительность здесь.

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

1 голос
/ 13 сентября 2011

Или, может быть, без для:

List<List<int>> m_indexes = new List<List<int>>()  { new List<int>(){367, 40, 74, 15},
new List<int>(){535, 226, 74, 15}, 
new List<int>(){368, 313, 74, 15},
new List<int>(){197, 316, 74, 15}, 
new List<int>(){27, 226, 74, 15},
new List<int>(){194, 41, 74, 15} };

var res = m_indexes.Select(x => x.Sum()).Sum();
1 голос
/ 13 сентября 2011

Простой способ LINQ:

var columnSums = m_indexes.OfType<int>().Select((x,i) => new { x, col = i % m_indexes.GetLength(1) } )
    .GroupBy(x => x.col)
    .Select(x => new { Column = x.Key, Sum = x.Sum(g => g.x) });

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

...