java – 为什么在四核机器上使用多个线程时,此代码没有看到任何显着的性能提升?

前端之家收集整理的这篇文章主要介绍了java – 为什么在四核机器上使用多个线程时,此代码没有看到任何显着的性能提升?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我写了一些 Java代码来了解更多关于Executor框架的信息.

具体来说,我编写了验证Collatz Hypothesis代码 – 这表示如果您迭代地将以下函数应用于任何整数,则最终得到1:

f(n)=((n%2)== 0)? n / 2:3 * n 1

CH仍然未经证实,我认为这将是了解执行人员的好方法.每个线程分配一个要检查的整数的范围[l,u].

具体来说,我的程序需要3个参数 – N(我想检查CH的数字),RANGESIZE(线程必须处理的间隔的长度),NTHREAD是线程池的大小.

我的代码工作正常,但是当我从1到4个线程时,我看到的加速度要低得多 – 30%的顺序.

我的逻辑是计算完全是cpu限制,每个子任务(检查固定大小范围的CH)大致相同的时间.

有人有什么想法,为什么我没有看到3到4倍的速度增长?

如果您可以增加线程数(连同机器,JVM和操作系统)也可以报告您的运行时间.

细节

运行时:

java -d64 -server -cp. Collat​​z 10000000 1000000 4 => 4线程,需要28412毫秒

java -d64 -server -cp. Collat​​z 10000000 1000000 1 => 1个线程,需要38286毫秒

处理器:

Quadcore Intel Q6600,2.4GHZ,4GB.机器卸载.

Java的:

java版本“1.6.0_15”
Java(TM)SE运行时环境(build 1.6.0_15-b03)
Java HotSpot(TM)64位服务器虚拟机(构建14.1-b02,混合模式)

OS:

Linux quad0 2.6.26-2-amd64#1 SMP Tue Mar 9 22:29:32 UTC 2010 x86_64 GNU / Linux

代码:(我无法获得代码发布,我认为SO要求太长了,源码在Google Docs上可用

import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class MyRunnable implements Runnable {
  public int lower;
  public int upper;

  MyRunnable(int lower,int upper) {
    this.lower = lower;
    this.upper = upper;
  }

  @Override
  public void run() {
    for (int i = lower ; i <= upper; i++ ) {
      Collatz.check(i);
    }
    System.out.println("(" + lower + "," + upper + ")" );
  }
}


public class Collatz {

  public static boolean check( BigInteger X ) {
    if (X.equals( BigInteger.ONE ) ) {
      return true;
    } else if ( X.getLowestSetBit() == 1 ) { 
      // odd
      BigInteger Y = (new BigInteger("3")).multiply(X).add(BigInteger.ONE);
      return check(Y);
    } else {
      BigInteger Z = X.shiftRight(1); // fast divide by 2
      return check(Z);
    }
  }

  public static boolean check( int x ) {
    BigInteger X = new BigInteger( new Integer(x).toString() );
    return check(X);
  }

  static int N = 10000000;
  static int RANGESIZE = 1000000;
  static int NTHREADS = 4;

  static void parseArgs( String [] args ) {

    if ( args.length >= 1 ) {
      N = Integer.parseInt(args[0]);
    }
    if ( args.length >= 2 ) {
      RANGESIZE = Integer.parseInt(args[1]);
    }
    if ( args.length >= 3 ) {
      NTHREADS = Integer.parseInt(args[2]);
    }
  }

  public static void maintest(String [] args ) {
    System.out.println("check(1): " + check(1));
    System.out.println("check(3): " + check(3));
    System.out.println("check(8): " + check(8));
    parseArgs(args);
  }

  public static void main(String [] args) {
    long lDateTime = new Date().getTime();
    parseArgs( args );
    List<Thread> threads = new ArrayList<Thread>();
    ExecutorService executor = Executors.newFixedThreadPool( NTHREADS );
    for( int i = 0 ; i < (N/RANGESIZE); i++) {
      Runnable worker = new MyRunnable( i*RANGESIZE+1,(i+1)*RANGESIZE );
      executor.execute( worker );
    }
    executor.shutdown();
    while (!executor.isTerminated() ) {
    }
    System.out.println("Finished all threads");
    long fDateTime = new Date().getTime();
    System.out.println("time in milliseconds for checking to " + N + " is " + 
                            (fDateTime - lDateTime )  + 
                            " (" + N/(fDateTime - lDateTime ) + " per ms)" );
  }
}

解决方法

繁忙的等待可能是一个问题:
while (!executor.isTerminated() ) { 
}

您可以使用awaitTermination():

while (!executor.awaitTermination(1,TimeUnit.SECONDS)) {}
原文链接:https://www.f2er.com/java/120433.html

猜你在找的Java相关文章