Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这个Java代码没有利用所有的CPU核?_Java_Scalability_Cpu_Multicore_Scaling - Fatal编程技术网

为什么这个Java代码没有利用所有的CPU核?

为什么这个Java代码没有利用所有的CPU核?,java,scalability,cpu,multicore,scaling,Java,Scalability,Cpu,Multicore,Scaling,当使用正确的参数启动时,附带的简单Java代码应该加载所有可用的cpu内核。比如说,你从 java VMTest 8 int 0 它将启动8个线程,这些线程除了循环和向整数加2之外什么也不做。在寄存器中运行甚至不分配新内存的东西 我们现在面临的问题是,在运行这个简单的程序(当然有24个线程)时,我们没有加载24核的机器(AMD 2个插槽,每个插槽有12核)。类似的情况发生在2个程序中,每个程序有12个线程或更小的机器 因此,我们怀疑JVM(Linux x64上的Sun JDK 6u20)不能很好

当使用正确的参数启动时,附带的简单Java代码应该加载所有可用的cpu内核。比如说,你从

java VMTest 8 int 0

它将启动8个线程,这些线程除了循环和向整数加2之外什么也不做。在寄存器中运行甚至不分配新内存的东西

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

因此,我们怀疑JVM(Linux x64上的Sun JDK 6u20)不能很好地扩展

是否有人看到类似的东西或有能力运行它,并报告它是否在他/她的机器上运行良好(请大于等于8个内核)?想法

我在AmazonEC2上也尝试过,它有8个内核,但是虚拟机的运行方式似乎与真实的机器不同,因此加载行为完全奇怪

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);
    }
}
package.com.test;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.Future;
导入java.util.concurrent.TimeUnit;
公共类VMT测试
{
公共类IntTask实现可运行
{
@凌驾
公开募捐
{
int i=0;
while(true)
{
i=i+2;
}
}
}
公共类StringTask实现可运行
{
@凌驾
公开募捐
{
int i=0;
字符串s;
while(true)
{
i++;
s=“s”+整数值(i);
}
}
}
公共类ArrayTask实现可运行
{
私人最终整数大小;
公共阵列任务(整数大小)
{
这个。大小=大小;
}
@凌驾
公开募捐
{
int i=0;
字符串[]s;
while(true)
{
i++;
s=新字符串[大小];
}
}
}
公共void doIt(字符串[]args)引发InterruptedException
{
最后一个字符串命令=args[1]。trim();
ExecutorService executor=Executors.newFixedThreadPool(Integer.valueOf(args[0]);
对于(int i=0;i
我看不出你的代码有什么问题

然而,不幸的是,您不能在Java中指定处理器相关性。因此,这实际上取决于操作系统,而不是JVM。这一切都是关于你的操作系统如何处理线程

您可以将Java线程拆分为单独的进程,并用本机代码将它们包装起来,以便为每个核心放置一个进程。当然,这会使通信复杂化,因为这将是进程间通信,而不是线程间通信。无论如何,这就是像boink这样流行的网格计算应用程序的工作原理


否则,您就只能由操作系统安排线程了。

我想这是JVM/OS固有的,不一定是您的代码。查看Sun提供的各种JVM性能调优文档,例如,其中建议在Linux上使用
numactl
来设置相关性


祝你好运

我注意到,即使是在C上,紧密循环也经常会出现类似的问题。您还将看到不同操作系统之间的巨大差异

根据您使用的报告工具,它可能不会报告某些核心服务使用的CPU

Java往往非常友好。您可以在linux中尝试同样的方法,但将进程优先级设置为负数,然后查看它是如何工作的

如果您的jvm没有使用绿色线程,那么在应用程序中设置线程优先级也可能会有所帮助

很多变量。

uname-a 2.6.18-194.11.4.el5#1 SMP周二9月21日05:04:09美国东部夏令时2010年x86_64 x86_64 x86_64 GNU/Linux

英特尔(R)至强(R)CPU E5530@2.40GHz

Java 1.6.0_20-b02

16个内核,程序消耗100%的cpu,如vmstat所示


有趣的是,我之所以读这篇文章,是因为我怀疑我的应用程序没有利用所有的内核,因为cpu利用率从未增加,但响应时间开始恶化

显然,您的虚拟机正在所谓的“客户端”模式下运行,所有Java线程都映射到一个本机OS线程,因此由一个CPU内核运行。尝试使用
-server
开关调用JVM,这将纠正问题


如果您得到一个:
错误:找不到“服务器”JVM
,您必须将
server
目录从JDK的
jre\bin
目录复制到jre的
bin

这不是问题,用较少的线程运行两个虚拟机不会对游戏产生太大的影响。每个核心运行一个JVM,每个核心运行两个线程如何?您可能想更改您的问题,因为我回答了“为什么此Java代码没有利用所有CPU内核?”对于误解,很抱歉,但问题是:“…此Java代码…”。它很简单,没有锁定,没有同步,没有内存