#c# #arrays #numbers #byte #task-parallel-library
#c# #массивы #числа #байт #задача-параллельная-библиотека
Вопрос:
Мне нужно найти суммы всех байтовых значений из файлов объемом более 5 ГБ. Вопрос в производительности: когда я использую только обычные выражения, такие как .Sum()
, .Aggregate()
или foreach
, и делаю все это в Parallel.For
циклах — это работает, но мне сказали, что есть какая-то программа в 10 раз быстрее. Это мое. (Также я использую 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. Ваш вопрос неясен, вы спрашиваете о том, как сделать эту программу быстрее в соответствии с 10x, о котором вы слышали? Кроме того, не уверен, почему вы заявляете, что
Task
это может снизить производительность. Это может иметь любой эффект, зависит от того, используете ли вы его правильно или неправильно.2. я бы просто поиграл с вашим буфером чтения и размером блока, и использование файла с отображением в памяти кажется сомнительным. Как сделать этот вопрос быстрее, не подходит для stackoverflow
3. @peeyushsingh — Не имеет значения, используете ли вы его правильно или неправильно. Код может быть «правильным», но работать плохо, и вы можете взломать код, который «неправильно» вызывается, и быть быстрым.
4. @peeyushsingh, да, я знаю, что на .NET есть какая-то программа, которая делает это в 10 раз быстрее. Я думал, что это из-за «как можно большего параллелизма», но этот подход не помог.
5. Если это в .net, просто декомпилируйте их и посмотрите, что они делают
Ответ №1:
Вы могли бы попробовать выгрузить суммирование байтов в поток-потребитель, но в конечном итоге скорость, с которой вы можете получить сумму, ограничена скоростью, с которой вы можете прочитать байты из файловой системы. Лично я проводил эксперименты с чтением одного большого файла с помощью нескольких считывателей, работающих в нескольких потоках, и я видел улучшение не более чем в 2 раза, и только при чтении с моего SSD. С моего внешнего диска чтение с помощью одного устройства чтения на самом деле происходит быстрее. Я не использовал MemoryMappedFile
, только stream.Read
.