【发布时间】:2017-03-20 11:49:31
【问题描述】:
我有一些功能的大列表(最多 500 000 个)。 我的任务是为每个函数生成一些图表(它可以独立于其他函数)并将输出转储到文件(可以是多个文件)。 生成图表的过程可能很耗时。
我还有 40 个物理内核和 128GB 内存的服务器。
我曾尝试使用 java Threads/ExecutorPool 实现并行处理,但似乎并未使用处理器的所有资源。 在某些输入上,该程序需要长达 25 小时才能运行,并且根据 htop 只有 10-15 个内核在工作。
所以我尝试的第二件事是创建 40 个不同的进程(使用 Runtime.exec)并在它们之间拆分列表。 此方法使用处理器的所有资源(所有 40 个内核上的 100% 负载),并且在前面的示例中将性能提高了 5 倍(只需要 5 小时,这对我的任务来说是合理的)。 但是这种方法的问题是,每个java进程都是独立运行的,独立消耗内存。在某些情况下,并行工作 5 分钟后会消耗所有 128gb 的内存。我现在使用的一种解决方案是,如果 Runtime.totalMemory > 2GB,则为每个进程调用 System.gc()。这会稍微降低整体性能(先前输入为 8 小时),但会使内存使用量保持在合理的范围内。 但此配置仅适用于我的服务器。如果在 40 核 64GB 运行的服务器上运行,则需要调优 Runtime.totalMemory > 2GB 条件。
那么问题是避免这种激进的内存消耗的最佳方法是什么?
运行单独的进程来执行并行作业是正常的做法吗?
Java 中是否有其他并行方法(可能是 fork/join?)使用 100% 的处理器物理资源。
【问题讨论】:
-
你的
Executor中有多少线程? -
Fork/join 在内部使用执行器池。
-
有什么理由不能让 Java 使用所有 128GB 的 RAM?如果没有其他需要它,它就会浪费。自己调用
System.gc()也不是一个解决方案,因为 Java 非常有能力管理自己的内存。 -
另外,如果你的进程是多线程的,你可能不应该运行其中的 40 个。
-
@kgeorgiy 我试过 Runtime.getRuntime().availableProcessors() + 1 和 Runtime.getRuntime().availableProcessors() *2 没有真正的区别
标签: java multithreading parallel-processing