2016-02-04 2 views
1

Что является самым быстрым способом записи массива int [] в массив byte [], но только LSB (последние 8 бит)? Я использовал for цикл и битмаску bArray[i] = (byte)(iArray[i] & 0xFF), но массив очень длинный (+ 900k), и это занимает около 50 мс. Вы знаете, может быть, другой более быстрый вариант?C# int [] array to byte [] array only LSB

+0

Вы хотите, чтобы LSB каждого int в массиве int в массив байтов? – bpgeck

+1

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

+0

@bpgeck yes, LSB каждого int в массиве int в байтовый массив. То есть 200 значений LSB 16-разрядного массива int до 200 значений 8-битового байтового массива. – Archont

ответ

1

Вы можете попробовать распараллеливания нагрузки:

Parallel.For(0,iArray.Length, i => bArray[i] = (byte)(iArray[i] & 0xFF)); 

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

Что вы делаете, что 50 мс слишком медленно?

+0

Я хочу отобразить массив изображений, но моя функция принимает только байты в качестве параметров - 256 оттенков серого достаточно и быстрее, чем 16 бит. – Archont

1

Часть медлительности исходит из необходимости читать больше данных, чем нужно: когда вы делаете

array[i] & 0xFF 

вы читаете все четыре байта в int, только уронить три наиболее значимых из них.

Вы можете избежать этих накладных расходов с помощью небезопасного кода. Имейте в виду, что подход ниже, предполагает небольшой архитектуры Endian:

static unsafe void CopyLsbUnsafe(int[] from, byte[] to) { 
    fixed (int* s = from) { 
     fixed (byte* d = to) { 
      byte* sb = (byte*) s; 
      int* db = (int*)d; 
      int* end = db + to.Length/4; 
      while (db != end) { 
       *db++ = (*(sb + 0) << 0) 
         | (*(sb + 4) << 8) 
         | (*(sb + 8) << 16) 
         | (*(sb + 12) << 24); 
       sb += 16; 
      } 
     } 
    } 
} 

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

Мое тестирование показывает респектабельное улучшение на 60% по сравнению с простым циклом.