Я пытаюсь найти способ прочитать файл в массив с «пробелами»:
Таким образом, прочитанные данные находятся в байтовом массиве buffer
на позициях buffer[0], buffer[2], .., buffer[2*i]
без каких-либо существенных потерь скорости.
Более конкретно, я хочу прочитать это интуитивно (т.е. b[0], b[4], ..., b[i * 4]
).
Это каким-либо образом возможно (C #, C ++) или я должен искать другой подход?
Немного больше предыстории:
Я пытаюсь ускорить алгоритм хеширования (хэширует файл по блокам, конкататирует хэши, хэширует и принимает полученный хеш).
Идея состояла в том, чтобы / было взять SSE3 и сделать 4 блока «параллельно», поэтому мне нужны данные таким образом, чтобы я мог легко загрузить данные в регистры.
(Замечательная) библиотека, которую я написал в C ++, дает хорошие результаты (то есть в 4 раза быстрее), но переупорядочивание данных сокращает прирост скорости.
В настоящее время я читаю файл блочно, а затем переупорядочить целые числа (C #):
unsafe {
uint* b = (uint*)buffer.ToPointer() + chunkIndex;
fixed(byte* blockPtr = chunk) {
uint* blockIntPtr = (uint*)blockPtr;
for(int i = 0; i < 9500 * 1024 / 4; i += 4) {
*(b + 00) = blockIntPtr[i + 0];
*(b + 04) = blockIntPtr[i + 1];
*(b + 08) = blockIntPtr[i + 2];
*(b + 12) = blockIntPtr[i + 3];
b += 16;
}
}
}
chunk
это байтовый массив и chunkIndex
является целым числом, переданным как параметры метода.
buffer
это uint32_t*
указатель, который выделяется моим кодом C ++.
Проблема в том, что это занимает слишком много времени. Вызов вышеуказанного кода 4 раза занимает около 90 мс, а хеширование — 3 мс.
Большое расхождение кажется мне немного странным, но оно дает правильные хэши.
в с ++ я бы сделал что-то вроде:
uint* b = (uint*)buffer;
for(int i = 0; i < 9500 * 1024; i ++) {
//read 4 ints
*(b+i+0) = blockIntPtr[i + 0];
*(b+i+1) = blockIntPtr[i + 1];
*(b+i+2) = blockIntPtr[i + 2];
*(b+i+3) = blockIntPtr[i + 3];
//skip next 12 ints
b += 16;
}
Других решений пока нет …