Эффективно суммируйте все байтовые значения из больших файлов - PullRequest
0 голосов
/ 11 апреля 2019

Мне нужно найти суммы всех значений байтов из файлов 5+ ГБ. Вопрос в производительности: когда я использую только обычные выражения, такие как .Sum(), .Aggregate() или foreach, и делаю все это в циклах Parallel.For - это работает, но мне сказали, что есть какая-то программа 10x Быстрее. Это мое. (Также я использую экземпляр FileStream с асинхронным режимом и MemoryMappedFile для чтения)

// ... Above there is some Parallel.For loop
// ... Which is about to read file in chunks
// Prepare array to read bytes 
Byte[] chunk = new Byte[readingChunkSize];
// Create an accessor to perform it
using (var viewAccessor = memMappedFile.CreateViewAccessor(overallMemoryOffset, readingChunkSize, MemoryMappedFileAccess.Read))
{
    // Loading desired data
    viewAccessor.ReadArray(
        0,
        chunk,
        0,
        Convert.ToInt32(readingChunkSize));
}
// Summing all the byte values 
Int64 sumFragment = 0;
for (Int64 i = 0; i < readingChunkSize; i++)
{
    sumFragment += chunk[i];
}
// Adding it to result
Interlocked.Add(ref bytesSum, sumFragment);

Полагаю, это что-то неочевидное, потому что добавление асинхронных операций, таких как Task, только снижает производительность.

1 Ответ

0 голосов
/ 11 апреля 2019

Вы можете попытаться выгрузить суммирование байтов в поток потребителя, но в конечном итоге скорость, с которой вы можете получить сумму, ограничена скоростью, с которой вы можете читать байты из файловой системы.Лично я провел эксперименты с чтением одного большого файла с использованием нескольких считывателей, работающих в нескольких потоках, и я увидел улучшение не более чем в 2 раза, и только при чтении с моего SSD.С моего внешнего диска на самом деле быстрее читать с одного читателя.Я не использовал MemoryMappedFile, только stream.Read.

...