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

时间:2012-09-30 03:37:09

标签: 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]);
    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);

    }
}

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:4)

据我了解您的代码,您可以并行运行每个试用版。如果您的CPU有多个内核,它会相应地运行得更快。

(已编辑)

通常,我会将算法转换为Callable,创建 tens ,(每个维度,每个州等一个)然后使用Executors.newFixedThreadPool ()创建一个合理大小的线程池(例如,对于我的英特尔i3笔记本电脑,4个线程)并调用invokeAll()。 More details in this blog post

然而,在你的100,000例中,这种效果并不好。 理想的方式是使用CompletionService在完成作业时重新提交作业。这开始变得复杂。

一种更简单,更有效的方法(但仍然更快)可能是

  1. 创建一个包含10个BrownianWalkers的集合。请注意,如果 他们在开始时设置x和y = 0,它们可以重用。所以你只是
  2. 需要创建此列表
  3. 创建fixedThreadPool
  4. 在i = 0 ... 10000 {
  5. 的循环中
  6. 调用submitAll()。
  7. 循环结果(期货)并将它们添加到您的总和中 }
  8. 你将浪费一点时间等待所有人完成,但仍然应该有一个显着的加速。由于大多数处理器都有2,4,8等核心,稍微改进就是使集合的功率为2(而不是10,这使数学变得简单)

答案 1 :(得分:0)

为了找到它将运行多长时间,就是找到函数的运行复杂度O(N ^ 2)。我相信。

答案 2 :(得分:0)

这应该是一个有效的并行实现:

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

    }

}

答案 3 :(得分:0)

至少有三种方法可以让您的代码更快,从更有效到最不有效列出:

  1. 降低算法的复杂性。目前,您的算法的时间复杂度为O(N^2):这意味着完成处理所需的时间与平方成正比输入的长度。您可能需要重新访问算法以减少不必要的计算或对中间结果应用优化。

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

  3. 使用更快的机器。如果算法没有以其他方式改进,那么加快速度的唯一方法就是更快地运行它。