线性搜索和反向线性搜索没有相同的执行时间

时间:2013-11-29 07:04:23

标签: java algorithm search operating-system cpu-architecture

我编写了代码来实现线性搜索(从数组的开头开始)和反向线性搜索(从数组的结尾开始)。现在,当我对1000个数字,1000次(每次使用不同的键)的样本运行程序时,这是累积结果。

总时间LS:814632

总时间RLS:581558

我想知道为什么我们在执行时间上有这么明显的差异。我用system.nanoTime()来检查时间。我认为,考虑到1000的大量分布(将两个函数称为1000次),时间差异不应该太大,因为密钥可能属于1000个索引中的任何一个。

    public static void main(String[] args) throws AWTException, Exception {
            long val[][] = new long[1000][3];
             for(int i=0;i<1000;i++)
             {
               val[i]=   testMethod();
             }
            long ls=0;
            long rls=0;
            long bls=0;
             for(int i=0;i<1000;i++)
             {
                ls= ls+val[i][0];
                rls=rls+val[i][1];
                bls=bls+val[i][2];
             }

             System.out.println("Total Time LS :" + ls);
             System.out.println("Total time RLS : " + rls);
             System.out.println("Total time BLS : " + bls);
        }

    public static long[] testMethod()
    {   long[] val=new long[3];
        int[] arr= new int[1000];
        Random r = new Random();
        for(int i=0;i<1000;i++)
        {
            arr[i]=r.nextInt()%99999;
        }

        int i= Math.abs(r.nextInt()%1000);
        int key =arr[i] ;
     //   int key = arr[900];
    //    System.out.println(i);
        long sysTime1=System.nanoTime();
        int pos_LS= LS(arr,key);
        long sysTime2=System.nanoTime();
        long t=sysTime2-sysTime1;
        val[0]=t;
   //     System.out.println("LS Time : " + t);

         sysTime1=System.nanoTime();
        int pos_RLS=RLS(arr,key);
         sysTime2=System.nanoTime();
         t=sysTime2-sysTime1;
   //     System.out.println("RLS Time : " + t);
        val[1]=t;



        sysTime1=System.nanoTime();
       int pos_BLS=BLS(arr,key);
        sysTime2=System.nanoTime();
        t=sysTime2-sysTime1;
  //     System.out.println("BLS Time : " + t);
       val[2]=t;



        return val;
    }
    public static int LS(int[] arr, int key)
    {
        for(int i=0;i<arr.length;i++)
        {
            if(arr[i]==key)
            {
                return i;
            }
        }
        return -1;
    }



    public static int RLS(int[] arr, int key)
    {   
        for(int i=arr.length-1;i>=0;i--)
        {  
            if(arr[i]==key)
            {   
                return i;
            }
        }
        return -1;
    }

    public static int BLS(int[] arr, int key)
    {
        int len=arr.length;
        for(int i=0;i<len/2;i++)
        {
            if(arr[i]==key || arr[len-1-i]==key)
            {
                if(arr[i]==key)
                {
                    return i;
                }
                else 
                {
                    return len-i-1;
                }

            }
        }
        return -1;

    }

第二轮: 总时间LS:868477 总时间RLS:604649

第3次运行: 总时间LS:648266 总时间RLS:765009

第4次运行: 总时间LS:877037 总时间RLS:619652

5 个答案:

答案 0 :(得分:2)

您的实验中未提及大量细节。

首先,如果每次都生成随机数据集,则无法得出任何结论。如果您生成一次巨大的数据集并且始终将这些数据用于这些测试,那么最好。在此之前,我们不能排除线性搜索可能面临对抗性输入。请记住,O(f(n))符号只表示,“它的性能不会比这更差”(在线性搜索的情况下,线性函数)。它没有声明任何关于多次运行的性能一致性。 (见脚注。)

接下来,运行总计是什么意思?你是否添加了每次搜索的执行时间?这不是衡量统计数据的好方法。最好是绘制单独的时间并检查运行时间分布的差异。

(附录:我认为每个进行基准测试的程序员都应该阅读this post by Zed Shaw。Shaw建议采用标准偏差的另一种方法是查看百分位数。就像标准偏差一样,它可以让你排除可能的异常值可能会扭曲你的总数。)

脚注:多次运行的效果分析属于摊销分析。然而,与更常见的渐近分析(确定单个运行的性能)不同,它不适用于所有算法。摊销算法和数据结构通常执行额外的内务管理任务,以“摊销”其他业务的绩效成本。

答案 1 :(得分:1)

完全取决于要搜索的key

考虑您拥有此数据1 2 3 4 5 6 7 8 9

使用线性serch搜索2将比反向线性搜索花费更少的时间

使用反向线性搜索搜索8所需的时间比线性搜索更短

如果你搜索5,那么两者都会给你同样的时间

答案 2 :(得分:1)

如果生成一个新数组,然后运行LS,然后运行RLS,然后生成一个新数组并重复,这取决于计算机上的高速缓存大小,您可能会遇到数组不在LS缓存中的影响在RLS的缓存中。要验证缓存是否影响您的测试结果,您可能先运行RLS,然后运行LS(LS现在可以更快)。

答案 3 :(得分:1)

这完全取决于您的计算机体系结构和操作系统。但是,可以进行概述。

CPU一次运行大量进程,CPU只能执行命令。大多数基本操作都是CPU内的ALU操作。

将处理的数据存储在计算机内存中,在我们的案例中为RAMCPU caches。 CPU通过缓存数据运行得更快。如果数据不在缓存中,则从内存中获取(ram)。 ram是一个内存,其地址的数据有random access时间。

缓存中可能没有数据

无法保证可以在缓存中找到要处理的数据。它完全依赖于在CPU上运行的其他进程。这是我们的一个障碍。在线性搜索期间CPU何时以及多少次未达到缓存数据。

无法保证线性搜索将以先发制人的方式完成

进程不在单个操作中运行。 CPU决定进程运行的次数,然后切换到其他进程。它被称为Context Swithcig。此外,在执行进程期间,CPU中存在许多synchronization个问题。

上图显示了CPU内部的进程生命周期。因此,无法保证在CPU中运行时的线性搜索。

enter image description here

您显示问题的结果显示运行时间是可变的,因为我解释。最好在内存和时序分析中比较算法的BigO值。

另见

Main Memory

Processes

Process State

答案 4 :(得分:0)

我的猜测,它与编译器以及它们如何实现这些数组有关。地址空间中放置这些数组索引的位置,访问方式等等......

再次猜测我无法确定这一点。另一点值得注意的是,虽然记录的时间一直较高,但它们从未高出一个数量级。在学术计算机科学家的运行时观点中,这些都是在O(n)中完成的,那些时间反映了这一点。