Java 这需要多长时间才能运行?我如何加快速度

Java 这需要多长时间才能运行?我如何加快速度,java,performance,duration,Java,Performance,Duration,我正在运行一些代码来测试布朗运动和散度,我很好奇这段代码需要多长时间才能运行,以及如何加速这个过程。我对java比较陌生,所以目前的代码比较基础。我正在运行的参数是1000000 1000000 public class BrownianMotion { public static void main(String[] args) { /**starts vars for program*/ int N = Integer.parseInt(args[0]);

我正在运行一些代码来测试布朗运动和散度,我很好奇这段代码需要多长时间才能运行,以及如何加速这个过程。我对java比较陌生,所以目前的代码比较基础。我正在运行的参数是1000000 1000000

public class BrownianMotion {

    public static void main(String[] args) {

    /**starts vars for program*/

    int N = Integer.parseInt(args[0]);
    int T = Integer.parseInt(args[1]);
    double sqtotal = 0;
    double r;
    double avg;

    /**number of trials loop*/

    for (int count=0;count<T;count++) {

        /**started here so that x & y reset at each trial*/

        int x = 0;
        int y = 0;

        /**loop for steps*/
        for (int steps=0;steps<N;steps++) {

        r = Math.random();
        if      (r < 0.25) x--;
        else if (r < 0.50) x++;
        else if (r < 0.75) y--;
        else if (r < 1.00) y++;

        }
        /**squared total distance after each trial*/
        sqtotal = sqtotal + (x*x+y*y);

    }

    /**average of squared total*/

    avg = sqtotal/T;
    System.out.println(avg);

    }
}
公共类布朗运动{
公共静态void main(字符串[]args){
/**为程序启动变量*/
int N=Integer.parseInt(args[0]);
int T=Integer.parseInt(args[1]);
双倍sqtotal=0;
双r;
双平均值;
/**循环试验次数*/

for(int count=0;count要想知道这将运行多长时间,就要知道函数的运行复杂度O(N^2)。我相信。

要知道这将运行多长时间,就要知道函数的运行复杂度O(N^2)。我相信。

据我所知,您可以并行运行每个测试。如果您的CPU有多个内核,它将相应地运行得更快

(新增编辑)

通常,我会将算法转换为可调用的,创建十个(每个维度、每个状态等一个),然后使用Executors.newFixedThreadPool()创建一个大小合理的线程池(比如,对于我的Intel i3笔记本电脑,4个线程)并调用invokeAll()

但是,在您的100000示例中,这并不太有效。理想的方法是在作业完成时使用CompletionService重新提交作业。这会变得越来越复杂

一种更简单、效率不高(但速度更快)的方法可能是

  • 创建一个包含10个BrownianWalker的集合 它们在开始时将x和y设置为0,这样它们就可以被重用 需要创建此列表一次吗
  • 创建fixedThreadPool
  • 在i=0…10000的循环中{
  • 调用submitAll()
  • 循环计算结果(未来)并将其添加到您的总和中。
    }

  • 您将浪费一点时间等待所有操作完成,但仍然会有显著的加速。由于大多数处理器的内核为2、4、8等,因此稍微改进的是将集合的幂次设置为2(而不是10,这使数学变得简单)

    据我所知,您可以并行运行每个试用版。如果您的CPU有多个内核,它将相应地运行得更快

    (新增编辑)

    通常,我会将算法转换为可调用的,创建十个(每个维度、每个状态等一个),然后使用Executors.newFixedThreadPool()创建一个大小合理的线程池(比如,对于我的Intel i3笔记本电脑,4个线程)并调用invokeAll()

    但是,在您的100000示例中,这并不太有效。理想的方法是在作业完成时使用CompletionService重新提交作业。这会变得越来越复杂

    一种更简单、效率不高(但速度更快)的方法可能是

  • 创建一个包含10个BrownianWalker的集合 它们在开始时将x和y设置为0,这样它们就可以被重用 需要创建此列表一次吗
  • 创建fixedThreadPool
  • 在i=0…10000的循环中{
  • 调用submitAll()
  • 循环计算结果(未来)并将其添加到您的总和中。
    }

  • 您将浪费一点时间等待所有操作完成,但仍然会有显著的加速。由于大多数处理器的内核为2、4、8等,因此稍微改进的是将集合的幂次设置为2(而不是10,这使数学变得简单)

    这应该是一个可工作的并行实现:

    public class BrownianMotionThread extends Thread
    {
        int i;
        int T;
        int N;
        int numberOfProcessors;
        double sqtotal;
    
        BrownianMotionThread(int i, int T, int N, int numberOfProcessors)
        {
            this.i = i;
            this.T = T;
            this.N = N;
            this.numberOfProcessors = numberOfProcessors;
    
        }
    
        public void run()
        {
            double r;
            for (int count=i;count<T;count+= numberOfProcessors) {
    
                /**started here so that x & y reset at each trial*/
    
                int x = 0;
                int y = 0;
                    /**loop for steps*/
                for (int steps=0;steps<N;steps++) {
                    r = Math.random();
                if      (r < 0.25) x--;
                else if (r < 0.50) x++;
                else if (r < 0.75) y--;
                else if (r < 1.00) y++;
                    }
                /**squared total distance after each trial*/
                sqtotal = sqtotal + (x*x+y*y);
                }
        }
    }
    
    public class BrownianMotion {
        static double sqtotal;
        public static void main(String[] args) {
    
        /**starts vars for program*/
    
        final int N = Integer.parseInt(args[0]);
        final int T = Integer.parseInt(args[1]);
        final int numberOfProcessors = Runtime.getRuntime().availableProcessors();
        BrownianMotionThread[] threads = new BrownianMotionThread[numberOfProcessors];
        double avg;
    
        /**number of trials loop*/
        for(int i = 0; i < numberOfProcessors; i++)
        {
            threads[i] = new BrownianMotionThread(i,T,N,numberOfProcessors);
            threads[i].start();
        }
        for(int i = 0; i < numberOfProcessors; i++)
        {
            try 
            {
                threads[i].join();
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    
        for(int i = 0; i < numberOfProcessors; i++)
        {
            sqtotal += threads[i].sqtotal;
        }
    
    
        /**average of squared total*/
    
        avg = sqtotal/T;
        System.out.println(avg);
    
        }
    
    }
    
    公共类BrownianMotionThread扩展线程
    {
    int i;
    int T;
    int N;
    整数处理器;
    两倍总面积;
    布朗运动线程(inti,intt,intn,intnumberofprocessors)
    {
    这个。i=i;
    T=T;
    这个,N=N;
    this.numberOfProcessors=numberOfProcessors;
    }
    公开募捐
    {
    双r;
    
    对于(int count=i;count,这应该是一个工作并行实现:

    public class BrownianMotionThread extends Thread
    {
        int i;
        int T;
        int N;
        int numberOfProcessors;
        double sqtotal;
    
        BrownianMotionThread(int i, int T, int N, int numberOfProcessors)
        {
            this.i = i;
            this.T = T;
            this.N = N;
            this.numberOfProcessors = numberOfProcessors;
    
        }
    
        public void run()
        {
            double r;
            for (int count=i;count<T;count+= numberOfProcessors) {
    
                /**started here so that x & y reset at each trial*/
    
                int x = 0;
                int y = 0;
                    /**loop for steps*/
                for (int steps=0;steps<N;steps++) {
                    r = Math.random();
                if      (r < 0.25) x--;
                else if (r < 0.50) x++;
                else if (r < 0.75) y--;
                else if (r < 1.00) y++;
                    }
                /**squared total distance after each trial*/
                sqtotal = sqtotal + (x*x+y*y);
                }
        }
    }
    
    public class BrownianMotion {
        static double sqtotal;
        public static void main(String[] args) {
    
        /**starts vars for program*/
    
        final int N = Integer.parseInt(args[0]);
        final int T = Integer.parseInt(args[1]);
        final int numberOfProcessors = Runtime.getRuntime().availableProcessors();
        BrownianMotionThread[] threads = new BrownianMotionThread[numberOfProcessors];
        double avg;
    
        /**number of trials loop*/
        for(int i = 0; i < numberOfProcessors; i++)
        {
            threads[i] = new BrownianMotionThread(i,T,N,numberOfProcessors);
            threads[i].start();
        }
        for(int i = 0; i < numberOfProcessors; i++)
        {
            try 
            {
                threads[i].join();
            } 
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    
        for(int i = 0; i < numberOfProcessors; i++)
        {
            sqtotal += threads[i].sqtotal;
        }
    
    
        /**average of squared total*/
    
        avg = sqtotal/T;
        System.out.println(avg);
    
        }
    
    }
    
    公共类BrownianMotionThread扩展线程
    {
    int i;
    int T;
    int N;
    整数处理器;
    两倍总面积;
    布朗运动线程(inti,intt,intn,intnumberofprocessors)
    {
    这个。i=i;
    T=T;
    这个,N=N;
    this.numberOfProcessors=numberOfProcessors;
    }
    公开募捐
    {
    双r;
    
    对于(int count=i;count,至少有三种方法可以让代码运行得更快,从更有效到最无效列出:

  • 降低算法的复杂性。现在,您的算法有一个
    O(N^2)
    时间复杂度:这意味着完成处理所需的时间与输入长度的平方成正比。您可能需要重新访问算法以减少不必要的计算或对中间结果进行优化

  • 在算法中引入并行性。您的算法目前被实现为一大块按顺序执行的代码;也就是说(在硬件级别禁止指令流水线)每一条指令只有在前一条指令完成后才能执行。您可以重写代码,使用线程在多个处理器之间分割工作,也可以使用并行化框架为您完成大部分工作。这比第1点效率低。因为您机器中的处理器数是恒定的,因此它将l当输入到算法的输入的大小增加时,不进行缩放

  • 使用速度更快的机器。如果算法没有在其他方面得到改进,那么,提高速度的唯一方法就是加快运行速度


  • 至少有三种方法可以让代码运行得更快,从更有效到最无效依次列出:

  • 降低算法的复杂性。