为什么此Java代码没有利用所有CPU内核? [英] Why does this Java code not utilize all CPU cores?

查看:78
本文介绍了为什么此Java代码没有利用所有CPU内核?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用正确的参数启动时,随附的简单Java代码应加载所有可用的cpu内核.例如,您以

The attached simple Java code should load all available cpu core when starting it with the right parameters. So for instance, you start it with

java VMTest 8 int 0

java VMTest 8 int 0

,它将启动8个线程,除了循环并将2加到一个整数外,别无所求.在寄存器中运行的东西甚至不分配新的内存.

and it will start 8 threads that do nothing else than looping and adding 2 to an integer. Something that runs in registers and not even allocates new memory.

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

The problem we are facing now is, that we do not get a 24 core machine loaded (AMD 2 sockets with 12 cores each), when running this simple program (with 24 threads of course). Similar things happen with 2 programs each 12 threads or smaller machines.

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

So our suspicion is that the JVM (Sun JDK 6u20 on Linux x64) does not scale well.

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

Did anyone see similar things or has the ability to run it and report whether or not it runs well on his/her machine (>= 8 cores only please)? Ideas?

我也尝试在具有8个内核的Amazon EC2上进行此操作,但是虚拟机的运行方式似乎与真实设备不同,因此加载行为完全是奇怪的.

I tried that on Amazon EC2 with 8 cores too, but the virtual machine seems to run different from a real box, so the loading behaves totally strange.

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);
    }
}

推荐答案

我的代码没有发现任何问题.

I don't see anything wrong with your code.

但是,不幸的是,您无法在Java中指定处理器相似性.因此,这实际上取决于操作系统,而不是JVM.一切都与您的操作系统如何处理线程有关.

However, unfortunately, you can't specify the processor affinity in Java. So, this is actually left up to the OS, not the JVM. It's all about how your OS handles threads.

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

You could split your Java threads into separate processes and wrap them up in native code, to put one process per core. This does, of course, complicate communication, as it will be inter-process rather than inter-thread. Anyway, this is how popular grid computing applications like boink work.

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

Otherwise, you're at the mercy of the OS to schedule the threads.

这篇关于为什么此Java代码没有利用所有CPU内核?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆