代码之家  ›  专栏  ›  技术社区  ›  ReneS

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

  •  14
  • ReneS  · 技术社区  · 14 年前

    java VMTest 8 int 0版本

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

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

    有没有人看到过类似的东西,或者有能力运行它并报告它在他/她的机器上是否运行良好(请仅限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);
        }
    }
    
    5 回复  |  直到 14 年前
        1
  •  10
  •   Marcus Adams    14 年前

    我看不出你的代码有什么问题。

    但是,不幸的是,您不能在Java中指定处理器关联。所以,这实际上由操作系统决定,而不是由JVM决定。这都是关于你的操作系统如何处理线程。

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

        2
  •  4
  •   Volker Stolz    14 年前

    我猜这是JVM/OS固有的,不一定是你的代码。检查Sun的各种JVM性能优化文档,例如。 http://ch.sun.com/sunnews/events/2009/apr/adworkshop/pdf/5-1-Java-Performance.pdf 建议使用 numactl 在Linux上设置关联。

    祝你好运!

        3
  •  2
  •   johnidis    11 年前

    显然,您的VM是在所谓的“客户机”模式下运行的,在这种模式下,所有Java线程都映射到一个本机OS线程,因此由一个CPU内核运行。尝试调用JVM -server 开关,这应该能解决问题。

    Error: no 'server' JVM 找到了,你必须复制 server JDK的目录 jre\bin bin .

        4
  •  1
  •   Nikhil    14 年前

    找到对应内核版本 2.6.18-194.11.4.el5#1 SMP Tue 9月21日05:04:09美国东部时间2010 x86 x86 x86 x86 GNU/Linux

    英特尔(R)至强(R)CPU E5530@2.40GHz http://browse.geekbench.ca/geekbench2/view/182101

    Java 1.6.0_20-b02版

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

        5
  •  0
  •   Bill K    14 年前

    我注意到,即使在C语言中,一个紧循环也经常会出现这样的问题。根据操作系统的不同,您也会看到相当大的差异。

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

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

    很多变数。