如何根据CPU核心缩放线程?

发布于 2024-08-16 12:48:03 字数 166 浏览 5 评论 0 原文

我想用 Java 中的多线程解决数学问题。我的数学问题可以分为多个工作单元,我想在多个线程中解决。

我不想让固定数量的线程在其上工作,而是让线程数量与 CPU 核心数量相匹配。我的问题是,我无法在互联网上找到简单的教程。我发现的都是具有固定线程的示例。

这怎么能做到呢?你能提供例子吗?

I want to solve a mathematical problem with multiple threads in Java. my math problem can be separated into work units, that I want to have solved in several threads.

I don't want to have a fixed amount of threads working on it, but instead an amount of threads matching the amount of CPU cores. My problem is, that I couldn't find an easy tutorial in the internet for this. All I found are examples with fixed threads.

How can this be done? Can you provide examples?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凉栀 2024-08-23 12:48:03

您可以使用静态运行时方法来确定 Java 虚拟机可用的进程数,可用处理器。一旦确定了可用处理器的数量,就可以创建该数量的线程并相应地分配工作。

更新:为了进一步澄清,线程只是 Java 中的一个对象,因此您可以像创建任何其他对象一样创建它。因此,假设您调用上述方法并发现它返回 2 个处理器。惊人的。现在,您可以创建一个循环来生成新线程,并拆分该线程的工作,然后触发该线程。下面是一些伪代码来演示我的意思:

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

有关创建自己的线程的更多信息,前往本教程。另外,您可能需要查看线程池来创建线程。

You can determine the number of processes available to the Java Virtual Machine by using the static Runtime method, availableProcessors. Once you have determined the number of processors available, create that number of threads and split up your work accordingly.

Update: To further clarify, a Thread is just an Object in Java, so you can create it just like you would create any other object. So, let's say that you call the above method and find that it returns 2 processors. Awesome. Now, you can create a loop that generates a new Thread, and splits the work off for that thread, and fires off the thread. Here's some pseudocode to demonstrate what I mean:

int processors = Runtime.getRuntime().availableProcessors();
for(int i=0; i < processors; i++) {
  Thread yourThread = new AThreadYouCreated();
  // You may need to pass in parameters depending on what work you are doing and how you setup your thread.
  yourThread.start();
}

For more information on creating your own thread, head to this tutorial. Also, you may want to look at Thread Pooling for the creation of the threads.

ˉ厌 2024-08-23 12:48:03

您可能还想查看 java.util.concurrent 框架来了解这些内容。
像这样:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

或者

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

这比处理你自己的线程池等要好得多。

You probably want to look at the java.util.concurrent framework for this stuff too.
Something like:

ExecutorService e = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// Do work using something like either
e.execute(new Runnable() {
        public void run() {
            // do one task
        }
    });

or

    Future<String> future = pool.submit(new Callable<String>() {
        public String call() throws Exception {
            return null;
        }
    });
    future.get();  // Will block till result available

This is a lot nicer than coping with your own thread pools etc.

不语却知心 2024-08-23 12:48:03

选项 1:

newWorkStealingPool

public static ExecutorService newWorkStealingPool()

使用所有可用处理器作为目标并行级别创建工作窃取线程池。

使用此 API,您无需将核心数传递给 ExecutorService

此 API 的实现来自 grepcode

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

选项 2:

newFixedThreadPool 来自 Executors其他 newXXX 构造函数,返回 ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

将 nThreads 替换为 Runtime.getRuntime().availableProcessors()

选项 3: >

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

通过Runtime.getRuntime().availableProcessors() 作为 maximumPoolSize 的参数。

Option 1:

newWorkStealingPool from Executors

public static ExecutorService newWorkStealingPool()

Creates a work-stealing thread pool using all available processors as its target parallelism level.

With this API, you don't need to pass number of cores to ExecutorService.

Implementation of this API from grepcode

/**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

Option 2:

newFixedThreadPool API from Executors or other newXXX constructors, which returns ExecutorService

public static ExecutorService newFixedThreadPool(int nThreads)

replace nThreads with Runtime.getRuntime().availableProcessors()

Option 3:

ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue<Runnable> workQueue)

pass Runtime.getRuntime().availableProcessors() as parameter to maximumPoolSize.

鸠书 2024-08-23 12:48:03

Doug Lea(并发包的作者)有一篇可能相关的论文:
http://gee.cs.oswego.edu/dl/papers/fj.pdf

Fork Join 框架已添加到 Java SE 7 中。以下是更多参考资料:

http://www.oracle.com/technetwork /articles/java/fork-join-422606.html

Doug Lea (author of the concurrent package) has this paper which may be relevant:
http://gee.cs.oswego.edu/dl/papers/fj.pdf

The Fork Join framework has been added to Java SE 7. Below are few more references:

http://www.ibm.com/developerworks/java/library/j-jtp11137/index.html
Article by Brian Goetz

http://www.oracle.com/technetwork/articles/java/fork-join-422606.html

灼痛 2024-08-23 12:48:03

标准方法是 Runtime.getRuntime().availableProcessors() 方法。
在大多数标准 CPU 上,您将在此处返回最佳线程数(不是实际的 CPU 核心数)。因此,这就是您正在寻找的。

示例:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

不要忘记像这样关闭执行程序服务(否则您的程序将不会退出):

service.shutdown();

这里只是一个快速概述如何设置基于未来的 MT 代码(题外话,用于说明):

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

然后您需要跟踪您期望有多少结果并像这样检索它们:

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}

The standard way is the Runtime.getRuntime().availableProcessors() method.
On most standard CPUs you will have returned the optimal thread count (which is not the actual CPU core count) here. Therefore this is what you are looking for.

Example:

ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

Do NOT forget to shut down the executor service like this (or your program won't exit):

service.shutdown();

Here just a quick outline how to set up a future based MT code (offtopic, for illustration):

CompletionService<YourCallableImplementor> completionService = 
    new ExecutorCompletionService<YourCallableImplementor>(service);
    ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
    for (String computeMe : elementsToCompute) {
        futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
    }

Then you need to keep track on how many results you expect and retrieve them like this:

try {
  int received = 0;
  while (received < elementsToCompute.size()) {
     Future<YourCallableImplementor> resultFuture = completionService.take(); 
     YourCallableImplementor result = resultFuture.get();
     received++; 
  }
} finally {
  service.shutdown();
}
つ低調成傷 2024-08-23 12:48:03

在 Runtime 类上,有一个名为 availableProcessors() 的方法。您可以使用它来计算您有多少个 CPU。由于您的程序受 CPU 限制,因此您可能希望每个可用 CPU (最多)有一个线程。

On the Runtime class, there is a method called availableProcessors(). You can use that to figure out how many CPUs you have. Since your program is CPU bound, you would probably want to have (at most) one thread per available CPU.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文