繁体   English   中英

哪个循环更有效?

[英]What loop is more efficient?

我想知道哪个代码更有效,我有两个选择。 您会说哪个更有效?为什么? 谢谢。

选项A

array1 size is 1000
array2 size is 2000

for(int i = 0; i < array1.size(); i++)
{
    for(int j = 0; j < array2.size(); j++) {
        if(array1[i].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
        {
            doSomething();
            break;
        }
        if(j == array2.size()-1) // CHECKS IF ARRAY1 DID NOT FIND A MATCH
        {
            doSomething();
            break;
        }
        for(k = 0; k < array1.size(); k++)
        {
            if(array1[k].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                // BUT DOES NOTHING BECAUSE IT WAS DONE ALREADY UPSIDE
                break;
            }
            if(k == array1.size()-1) // CHECKS IF ARRAY2 DID NOT FIND A MATCH
            {
                doSomething();
                break;
            }
        }
    }
}

选项B

array1 size is 1000
array2 size is 2000


    for(int i = 0; i < array1.size(); i++)
    {
        for(int j = 0; j < array2.size(); j++) {
            if(array1[i].method() == array2[j].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                doSomething();
                break;
            }
            if(j == array2.size-1)  // CHECKS IF ARRAY1 HAS NO ARRAY2 MATCH
            {
                doSomething();
                break;
            }
        }
    }

    for(int j = 0; j < array2.size(); j++)
    {
        for(int i = 0; i < array1.size(); i++) {
            if(array2[j].method() == array1[i].method()) // CHECKS IF THERE'S AN EQUAL IN BOTH ARRAYS
            {
                // BUT DOES NOTHING BECAUSE IT WAS DONE ALREADY UPSIDE
                break;
            }
            if(i == array1.size-1) // CHECKS IF ARRAY2 HAS NO ARRAY1 MATCH
            {
                doSomething();
                break;
            }
        }
    }

我目前已经实现了OPTION B,我想知道是否应该转移到OPTION A,因为尽管Option A可能花费更多时间,但我不知道在执行两个循环还是一次执行所有迭代时是否会花费更多时间。 也许是一样的,我不太了解。

选项A为O(x ^ 2 * y)在您的情况下,选项B为O(x * y)选项A最多进行2,000,000,000次迭代,而B最多进行4,000,000次迭代。 当然,这不包括休息或继续。 我可能会坚持使用B。

正如@ Sploder12所说的那样,但是在循环中删除函数调用也可以带来很多好处,例如

int n= array.size()
for(int i=0; i<n; i++)

而不是

 for(int i=0; i<array.size(); i++)

除非您在循环内修改数组大小,否则重复的函数调用是浪费的。

关于@ Turing85的评论,我确实想知道是否有某种编译器机制可以发现以下事实:循环初始化中size()的返回值可能是常量,因此可以用常量“有效地最终”代替。 因此,我运行了以下两个循环,第一个没有手动进行持续优化:

int n1=a1.size();
for(int i=0; i<a1.size(); i++) {
    int n2=a2.size();
    for(int j=0; j<a2.size(); j++) {
        int n3=a3.size();
        for(int k=0; k<a3.size(); k++) {
            int candidate=a1.get(i)*a2.get(j)*a3.get(k);
            candidate+=n1*n2*n3;
            func(candidate);
        }//k
    }//j
}//i

第二个是手动不断优化:

int n1=a1.size();
for(int i=0; i<n1; i++) {
    int n2=a2.size();
    for(int j=0; j<n2; j++) {
        int n3=a3.size();
        for(int k=0; k<n3; k++) {
            int candidate=a1.get(i)*a2.get(j)*a3.get(k);
            candidate+=n1*n2*n3;
            func(candidate);
        }//k
    }//j
}//i

然后,我使用a1.size()= 100,a2.size()= 200和a3.size()= 300运行这些循环10次以获取时间,并针对每次变化的平均值和标准误差计算100次以200的顺序运行的循环是随机的。

在单个作业(即,对JVM的一次调用)中,将整个过程重复10次,以获得10个配对的均值和标准错误(该对中的一个成员来自优化的运行,另一个来自未优化的运行)。 在所有10种情况下,优化的平均时间都比未优化的平均时间快得多。 在每种情况下,均值之间的差异均大于标准误差的6.9倍,而在10种情况中,有7种均值之间的差异均大于15个标准误差。 数据如下。 为循环生成的字节码是不同的,尽管我不声称要讲字节码,但还存在对a * .size()的附加invokevirtual调用,我认为这是造成两个循环版本性能差异的原因。

因此,考虑到@ Turing85的评论,我想知道在什么条件下可以忽略“在此级别上”的优化吗?

openjdk版本“ 11” 2018-09-25 OpenJDK运行时环境18.9(内部版本11 + 28)OpenJDK 64位服务器VM 18.9(内部版本11 + 28,混合模式)

======数据======

100次优化循环平均每次运行6.412s,标准误为0.013; 100次未优化的循环平均每次运行6.502s,标准误为0.013

每100趟优化循环平均耗时5.143s,标准误为0.004; 每100次未优化的循环平均需要5.232s,标准误差为0.005

100次优化循环平均每次运行6.090s,标准误为0.006; 100次未优化的循环平均运行6.175秒,标准误为0.006

100次优化循环平均每次运行5.739s,标准误为0.005; 100次未优化的循环平均每次运行5.827s,标准误为0.005

100次优化循环平均每次运行5.613s,标准误为0.005; 100次未优化的循环平均每次运行5.697s,标准误差为0.004

100次优化循环平均每次运行6.045s,标准误为0.004; 100次未优化的循环平均运行6.121秒,标准误为0.004

每100趟优化循环平均耗时5.333s,标准误为0.003; 100次未优化的循环平均每次需要5.415s,标准误差为0.003

100次优化循环平均每次运行5.903s,标准误为0.009; 100次未经优化的循环平均每次需要5.972s,标准误为0.007

100次优化循环平均每次运行5.770s,标准误为0.005; 100次未优化的循环平均每次运行5.851秒,标准误为0.005

100次优化循环平均每次需要4.975s,标准误为0.004; 100次未优化的循环平均每次运行5.052s,标准误差为0.004

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM