У меня огромный массив байтов, который нужно обработать. Теоретически, можно было бы разрезать работу на ровные части и назначить их для разных потоков, чтобы повысить производительность на многоядерной машине.Многопоточные байтовые буферы медленнее, чем последовательные?
Я выделил ByteBuffer
для каждого потока и обрабатываемых частей данных каждый. Конечная производительность медленнее, чем с одним потоком, хотя у меня есть 8 логических процессоров. И это очень непоследовательно. Иногда один и тот же ввод удваивается, как медленный процесс, или больше. Почему это? Сначала данные загружаются в память, поэтому выполняются не более IO
операций.
размещаю мои ByteBuffers с помощью MappedByteBuffer
, потому что это быстрее, чем ByteBuffer.wrap()
:
public ByteBuffer getByteBuffer() throws IOException
{
File binaryFile = new File("...");
FileChannel binaryFileChannel = new RandomAccessFile(binaryFile, "r").getChannel();
return binaryFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, binaryFileChannel.size());
}
Я делаю свою параллельную обработку с помощью Executors
:
int threadsCount = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = Executors.newFixedThreadPool(threadsCount);
ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
for (ByteBufferRange byteBufferRange : byteBufferRanges)
{
Callable<String> task =() ->
{
performTask(byteBufferRange);
return null;
};
completionService.submit(task);
}
// Wait for all tasks to finish
for (ByteBufferRange ignored : byteBufferRanges)
{
completionService.take().get();
}
executorService.shutdown();
Параллельные задачи performTask()
использовать свои собственные ByteBuffer
экземпляров для чтения памяти из буфера, делать вычисления и так далее. Они не синхронизируют, не пишут и не влияют друг на друга. Любые идеи о том, что происходит не так, или это не хороший случай распараллеливания?
такая же проблема есть ByteBuffer.wrap()
и MappedByteBuffer
такой же.
Как вы бы сказали, массив? – Logan
Массированные буферы не являются файлами, загружаемыми в память. ОС динамически отображает фрагменты (страницы) содержимого файла в память, когда вы его читаете, и сворачивает данные для других данных, как только вы читаете в другом месте. Это означает, что вы используете очень мало фактической памяти, в то время как она может выглядеть так, как если бы у вас были террабайты в памяти. Но также означает, что перескакивание может потребовать повторного чтения с диска. – zapl
@LoganKulinski: Несколько 100MB – BullyWiiPlaza