java - 多线程 ByteBuffers 比顺序慢?

标签 java multithreading performance mappedbytebuffer

我有一个巨大的字节数组需要处理。从理论上讲,应该可以将工作分成均匀的部分并将它们分配给不同的线程以提高多核机器上的性能。

我为每个线程分配了一个ByteBuffer,并分别处理了部分数据。即使我有 8 个逻辑处理器,最终性能也比单线程慢。这也是非常不一致的。有时,相同的输入处理速度会慢一倍或更多。这是为什么?数据首先加载到内存中,因此不再执行 IO 操作。

我使用 MappedByteBuffer 分配我的 ByteBuffer因为它比 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 中。

最佳答案

正如@EJP 所提到的,磁盘并不是真正的多线程,尽管 SSD 可能会有所帮助。映射缓冲区的目的是让您不必自己管理内存;让操作系统来做吧,因为它的虚拟内存管理器和文件系统缓存比将它移动到 Java 的堆中要快,而且可能比您编写的任何内存管理代码都要快。

如果处理真的可以并行化,您最好让一个线程读取整个文件,将其分成 block (可能采用某种中间数据格式),然后让您的执行程序处理这些 block 。文件读取线程可以与其他线程并发运行,因此您无需读取整个文件即可开始处理。

您可能想尝试将执行程序的数量设置为 cores - 1,这样您就不会饿死文件读取线程。这将使操作系统有机会在没有上下文切换的情况下保持文件读取线程在单个内核上运行,这样您将获得良好的 IO 性能,同时使用其他内核执行 CPU 密集型工作。

仅供引用,这就是 Apache Spark 的构建目的。如果您需要处理更大的文件或需要比单个系统更快的处理速度,您可能需要查看它。

关于java - 多线程 ByteBuffers 比顺序慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37622485/

相关文章:

java - 如何从Android中的另一个 Activity 调用MapActivity的方法?

java - 用于自动帮助搜索所选文本的 Eclipse 插件

java - com.fasterxml.jackson.databind.JsonMappingException : Can not construct instance of : poja class no suitable constructor found

性能基准 CouchDB x 关系数据库

java - 我可以在 SWT 中使用 Clutter 吗?

java - 减少 Java 中同步块(synchronized block)的范围意外地损坏了我的 ArrayList,为什么会出现这种情况?

c# - 可以在Thread.Sleep期间引发ThreadAbortException吗?

Android 使新的异步任务在后台或 Dropbox Core API 问题中优先于其他任务

MySQL - 在提高查询性能方面需要帮助

asp.net - 提高 ASP.net WebForm 性能