码迷,mamicode.com
首页 > 编程语言 > 详细

线程数量与并行应用性能相关性的测试

时间:2015-10-06 23:34:11      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:

一直被一个问题所困扰,在并行应用中,任务划分的粒度达到多少合适?或者说,采用多线程时,启用多少线程能够达到最佳性能?

网上有一些资料给出了参考:

如果是CPU密集型任务,就需要尽量压榨CPU,参考值可以设为 NCPU+1

如果是IO密集型任务,参考值可以设置为2*NCPU

那么,我们就使用示例程序来实地测试一下吧!

ComputePerformanceTest.java

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 * @author pzy
 * @version 20151006
 * @funcion test the Performance of serial and parallel compute tasks
 */

public class ComputePerformanceTest {

    public static void main(String[] args) {    
        System.out.println("ComputePerformanceTest is running..");
        
        int processors = Runtime.getRuntime().availableProcessors();
        System.out.println(Integer.toString(processors) + " processor"
                + (processors != 1 ? "s are " : " is ")
                + "available");    

        //串行计算
        ComputeTaskManager manager = new ComputeTaskManager(20, 20);
        Long startTime = System.currentTimeMillis();
        manager.computeInSerial();
        System.out.printf("computeInSerial finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();
        
        //20线程并行计算
        manager = new ComputeTaskManager(20, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(20,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();
        
        //10线程并行计算
        manager = new ComputeTaskManager(10, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(10,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();

        //4线程并行计算
        manager = new ComputeTaskManager(4, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(4,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);    
        manager.close();    
        
        //2线程并行计算
        manager = new ComputeTaskManager(2, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(2,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);    
        manager.close();
    }
}

class ComputeTaskManager {
    private long start = 1;
    private long end = 1000000000;
    private long taskNum;
    ExecutorService pool;
    
    public ComputeTaskManager(int taskNum, int pooSize) {
        this.taskNum = taskNum;
        pool = Executors.newFixedThreadPool(pooSize);
    }
    
    public void close(){
        pool.shutdown();
    }
    
    public Long computeInSerial(){
        System.out.printf("=====computeInSerial() start=====%n");
        long sum = new SumTask(start, end).sum();
        System.out.printf("=====computeInSerial() end=====%n");
        return sum;
    }
    
    public Long computeInParallel(){
        System.out.printf("=====computeInParallel(%d) start=====%n", taskNum);
        //将任务分拆为多个子任务
        long aver = (end - start + 1)/ taskNum;
        long sum = 0;
        for (int i = 0; i < taskNum; i++) {
            try {
                long startNum = this.start + i * aver;
                long endNum = startNum + aver - 1;
                if(endNum > this.end)
                    endNum = this.end;    
                sum += pool.submit(new SumTask(startNum, endNum)).get();
                startNum = startNum + aver + 1;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.printf("=====computeInParallel(%d) end=====%n", taskNum);
        return sum;
    }    
}

class SumTask implements Callable<Long>{
    
    private long start;
    private long end;
    private int SUM_COUNT = 50;
    
    public SumTask(long start, long end) {
        this.start = start;
        this.end = end;    
    }

    public Long sum(){
        long sum = 0;
        for (int i = 0; i < SUM_COUNT; i++) {
            for (long j = start; j <= end; j++) {
                sum += j;
            }
        }    
        return sum;
    }

    @Override
    public Long call() throws Exception {
        // TODO Auto-generated method stub        
        return sum();
    }
}

 

IOPerformanceTest.java

import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/*
 * @author pzy
 * @version 20151006
 * @funcion test the Performance of serial and parallel IO tasks
 */

public class IOPerformanceTest {

    public static void main(String[] args) {    
        System.out.println("IOPerformanceTest is running..");
        
        //打印cpu核心数
        int processors = Runtime.getRuntime().availableProcessors();
        System.out.println(Integer.toString(processors) + " processor"
                + (processors != 1 ? "s are " : " is ")
                + "available");    
        
        //串行计算
        IOTaskManager manager = new IOTaskManager(20, 10);
        Long startTime = System.currentTimeMillis();
        manager.computeInSerial();
        System.out.printf("computeInSerial finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();
        
        //20线程并行计算
        manager = new IOTaskManager(20, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(20,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();
        
        //10线程并行计算
        manager = new IOTaskManager(10, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(10,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);
        manager.close();

        //4线程并行计算
        manager = new IOTaskManager(4, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(4,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);    
        manager.close();    
        
        //2线程并行计算
        manager = new IOTaskManager(2, 20);
        startTime = System.currentTimeMillis();
        manager.computeInParallel();
        System.out.printf("result of computeInParallel(2,20) finished ,costs %d milliseconds%n",System.currentTimeMillis() - startTime);    
        manager.close();
    }
}

class IOTaskManager {
    private int taskNum;
    ExecutorService pool;
    CountDownLatch countDownLatch;

    public IOTaskManager(int taskNum, int pooSize) {
        this.taskNum = taskNum;
        countDownLatch = new CountDownLatch(taskNum);
        pool = Executors.newFixedThreadPool(pooSize);
    }
    
    public void close(){
        pool.shutdown();
    }
    
    void computeInSerial(){
        System.out.printf("=====computeInSerial(%d) start=====%n", taskNum);
        for (int i = 0; i < taskNum; i++) {
            new IOTask(i).compute();
        }
        System.out.printf("=====computeInSerial(%d) end=====%n", taskNum);
        
    }
    
    void computeInParallel(){
        System.out.printf("=====computeInParallel(%d) start=====%n", taskNum);
        for (int i = 0; i < taskNum; i++) {
            pool.execute(new IOTask(i, countDownLatch));
        }    
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.printf("=====computeInParallel(%d) end=====%n", taskNum);
    }    
}

class IOTask implements Runnable{

    int num;
    CountDownLatch countDownLatch;
    
    public IOTask(int num) {
        this.num = num;
    }
    
    public IOTask(int num, CountDownLatch countDownLatch) {
        this.num = num;
        this.countDownLatch = countDownLatch;
    }
    
    public void compute(){
        
        try {
            Thread.currentThread();
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }    
        if(countDownLatch != null){
            
            long count = countDownLatch.getCount() - 1;
            //System.out.printf("[task %d] countDownLatch is %d%n", num, count);
            System.out.printf("task %d has finished %n", num);
            countDownLatch.countDown();
        }
    }
    
    @Override
    public void run() {
        // TODO Auto-generated method stub
        compute();
    }


}

 

测试环境:

PC1:联想Y450/INTEL CORE2 T6500 双核2线程/UBUNTU 14.04 64bit

PC2:联想G50-70/INTEL CORE I7-4510U 双核4线程/WIN8.1 64bit

测试过程:

在两台PC上分别运行测试程序,并统计性能数据,结果如下:

 

 《未完待续》

线程数量与并行应用性能相关性的测试

标签:

原文地址:http://www.cnblogs.com/pzy4447/p/4857903.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!