为什么这个Java代码不使用所有CPU内核?

Ren*_*neS 14 java cpu scaling scalability multicore

附加的简单Java代码应该在使用正确的参数启动时加载所有可用的cpu核心.例如,你开始使用它

java VMTest 8 int 0

它将启动8个线程,除了循环并将2添加到整数之外什么都不做.在寄存器中运行的东西,甚至不分配新的内存.

我们现在面临的问题是,当运行这个简单的程序(当然有24个线程)时,我们没有加载24核机器(AMD 2个插槽,每个12个核心).类似的事情发生在每12个线程或更小的机器的2个程序.

所以我们怀疑JVM(Linux x64上的Sun JDK 6u20)不能很好地扩展.

有没有人看到类似的东西或有能力运行它并报告它是否在他/她的机器上运行良好(> =仅8个核心)?想法?

我在带有8个内核的Amazon EC2上尝试过这个,但是虚拟机似乎与真正的盒子不同,因此加载的行为非常奇怪.

package com.test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class VMTest
{
    public class IntTask implements Runnable 
    {
        @Override
        public void run()
        {
            int i = 0;

            while (true)
            {
                i = i + 2;
            }
        }
    }
    public class StringTask implements Runnable 
    {
        @Override
        public void run()
        {
            int i = 0;

            String s;
            while (true)
            {
                i++;
                s = "s" + Integer.valueOf(i);
            }
        }
    }
    public class ArrayTask implements Runnable 
    {
        private final int size; 
        public ArrayTask(int size)
        {
            this.size = size;
        }
        @Override
        public void run()
        {
            int i = 0;

            String[] s;
            while (true)
            {
                i++;
                s = new String[size];
            }
        }
    }

    public void doIt(String[] args) throws InterruptedException
    {
        final String command = args[1].trim();

        ExecutorService executor = Executors.newFixedThreadPool(Integer.valueOf(args[0]));
        for (int i = 0; i < Integer.valueOf(args[0]); i++)
        {
            Runnable runnable = null;
            if (command.equalsIgnoreCase("int"))
            {
                runnable = new IntTask();
            }
            else if (command.equalsIgnoreCase("string"))
            {
                runnable = new StringTask();
            }
            Future<?> submit = executor.submit(runnable);
        }
        executor.awaitTermination(1, TimeUnit.HOURS);
    }

    public static void main(String[] args) throws InterruptedException
    {
        if (args.length < 3)
        {
            System.err.println("Usage: VMTest threadCount taskDef size");
            System.err.println("threadCount: Number 1..n");
            System.err.println("taskDef: int string array");
            System.err.println("size: size of memory allocation for array, ");
            System.exit(-1);
        }

        new VMTest().doIt(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ams 10

我没看到你的代码有什么问题.

但是,遗憾的是,您无法在Java中指定处理器关联.所以,这实际上是由操作系统而不是JVM完成的.这完全取决于您的操作系统如何处理线程.

您可以将Java线程拆分为单独的进程并将其包装在本机代码中,以便为每个核心放置一个进程.当然,这确实使通信变得复杂,因为它将是进程间而不是线程间.无论如何,这就是像boink这样流行的网格计算应用程序.

否则,您将受操作系统的支配来安排线程.