如何在 Java 中实现多核算法?
现代计算机拥有越来越多的核心。 我们想要改变当前的线性算法以使用这些核心。
仅当有空闲处理器时,拆分任何算法以使用不同的线程才有意义。
如果有免费处理器,是否有任何好的库可以帮助并行化某些步骤?
我将举一些例子。
- 如果只有一个处理器,那么创建多个线程是没有意义的。 它会降低速度。
- 如果在核心二人组上运行 2 个进程(服务器上的请求),那么启动线程也是没有意义的。
- 如果核心二人组上只有一个进程,那就有意义了。
抽象算法有4个步骤A、B、C和D。步骤A、B和C可以并行执行。 步骤 D 需要 A、B 和 C 的结果。
编辑:我的意思是数学算法。 无 IO、无事件等
Modern computers have more and more cores. We want to change our current linear algorithm to use these cores.
A splitting of any algorithm to use different threads only makes sense if there is a free processor.
Are there any good libraries that can help to parallelize some steps if there are free processors?
I will give some examples.
- If there is only one processor it makes no sense to create multiple threads. It will reduce the speed.
- If there run 2 processes (requests on a server) on a core duo it make also no sense to start threads.
- If there only one process on a core duo it make sense.
The abstract algorithm has 4 steps A, B, C and D. Steps A, B and C can execute parallel. Step D needs the results from A, B and C.
Edit: I means an mathematic algorithm. No IO, No events, etc
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这不一定是真的。
根据算法的不同,即使只有一个核心可用,将其拆分为多个线程通常也是有意义的。 如果有任何套接字、IO 等等待,您可以从中受益。 如果有 2 个进程,“其他”进程可能不会使用其他核心的 100%,因此线程在这里可以提供帮助。 在这种情况下,请相信您的操作系统能够正确处理它。
您始终可以使用 Runtime.availableProcessors() 检查处理器计数,以确定如何将其拆分为单独的线程。 或者,您可以使用线程池,它应该可以随着更多处理器而正确扩展。
不过,一般来说,如果算法适合并行化,我会设计您的算法以使用多个处理器。 大多数系统都会有更多可用的内核/处理器,如果您发现需要,您可以随时调整您的实现。 如果进程运行时间较长,则生成线程的开销将是值得的 - 如果它已经很快,则可能更值得查看其他地方进行优化。
This isn't necessarily true.
Depending on the algorithm, it often makes sense to split it into multiple threads even if there is only a single core available. If there is any waiting on sockets, IO, etc, you can get benefits from this. If there are 2 processes, the "other" process may not be using 100% of the other core, so threading can help here. Trust your OS in this case to handle it correctly.
You can always check the processor count with Runtime.availableProcessors() to determine how to split it into separate threads. Alternatively, you can use a threadpool, which should scale correctly with more processors.
In general, though, I would design your algorithm to use more than one processor if the algorithm makes sense to parallelize. Most systems will have more cores/processors available, and you can always tweak your implementation later if you find it needs it. If the process is long running, the overhead of generating the thread will be worth it - if it's already fast, it may be more worthwhile looking at other places to optimize.
查看 Java 5 及更高版本中的各种并发类。 您很可能需要一个 ThreadPoolExecutor - http:// /java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html。
ThreadPool 的适当值很可能因系统而异,具体取决于工作负载和硬件架构。 使其可由用户调节。
Look at the various concurrent classes in Java 5 and onwards. You most likely want a ThreadPoolExecutor - http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html.
The appropriate value of the ThreadPool will most likely vary from system to system depending on work load and hardware architechture. Make it user adjustable.
对于一些想法,请查看 JSR166 和 JSR166y (类似于 fork-将系统与工作窃取 (166) 和并行阵列 (166y) 结合起来。
一些不错的读物和对 Java 未来方向的概述。 看起来还不错(对高级并发和并行编程的强大支持)。
For some ideas have a look at JSR166 and JSR166y (something like fork-join system with work stealing (166) and parallel array (166y) ).
Some nice reading and overview of the future directions for Java. Looks not that bad (strong support for high level concurrent and parallel programming).
我经常有一个固定的线程池,它的线程数量动态地与处理器的数量相同(请参阅运行时)
我将任务添加到该线程池中,以便它使用所有可用的处理器。
我不认为您应该尝试在操作系统中重新发明进程调度程序。 它做得很好,所以让它做它擅长的事情。
I often have a fixed thread pool which is dynamically the same number of thread as the number of processors (see Runtime)
I add tasks to this thread pool so it uses all the processors available.
I don't believe you should try re-inventing the process scheduler in the operating system. It does a good job so let it do what it does well.
拥有比内核更多的线程/进程不一定是坏事。 如果您的代码是严格的数学代码,I/O 很少且没有副作用,那么核心和线程之间具有 1:1 对应关系是最佳选择。 但通常情况并非如此。 与时钟周期相比,I/O 需要花费亿万年的时间。 当操作系统可以换入另一个线程以继续运行时,为什么要在等待 I/O 时完全停止核心呢?
问题是没有很多语言/编译器可以为您做出并发决策。 您需要设计程序以利用并发性。 而且您可能需要为多个目标环境设计程序,这些目标环境通常不受您的控制。 因此,通常,最佳实践是为并行化有意义的事物创建线程,并让线程调度程序处理它。 线程调度程序应该调整为在有问题的特定硬件上使用,这比您为“出现的任何硬件”调整程序要好得多。
Having more threads/processes than cores is not necessarily a bad thing. If your code is strictly mathematical with little I/O and no side effects, then yes, having a 1:1 correspondence between cores and threads is optimal. But this is not usually the case. I/O takes eons compared to clock cycles. Why stall the core completely while waiting on I/O when the OS can swap in another thread to keep chugging along?
The problem is there aren't a lot of languages/compilers that will make the concurrency decision for you. You need to design your program to take advantage of concurrency. And you probably need to design your program for multiple target environment, usually not under your control. So usually, best practice is to make threads for things whatever it makes sense to parallelize and let the thread scheduler handle it. The thread scheduler should be tuned for use on the specific hardware in question far better than you can tune your program for "whatever hardware comes along".
这是使用 Ateji PX 表示法(Java 语言的扩展)的一行:
作为程序员,您的责任是表达哪里有并行执行的潜力,这就是并行的作用条“||” 在代码中。 调度程序现在能够充分利用可用硬件,即只要可用,就在三个不同的内核上运行 A、B 和 C。
这是一个非常高级的视图,A、B 或 C 内部可能会表现出更多的并行性。
This is a one-liner using the Ateji PX notation, an extension of the Java language:
Your responsability as a programmer is to express where there is a potential for parallel execution, that's the role of the parallel bars "||" in the code. The scheduler now is able to make the best use of available hardware, namely run A, B and C on three different cores whenever available.
This is a very high-level view, more parallelism may possibly be exhibited inside A, B or C.
我认为您需要 Javolution 的 ConcurrentContext。 请参阅 http://javolution.org/target/site/apidocs/ javolution/context/ConcurrentContext.html
I think you need a ConcurrentContext from Javolution. See at http://javolution.org/target/site/apidocs/javolution/context/ConcurrentContext.html