哪些操作耗时,以及如何避免这些操作

What operations are time consuming and how to avoid them?

本文关键字:操作 何避免      更新时间:2023-10-16

我是c++的新手,我想学习如何优化程序的速度。我目前正在编写一个程序,计算从1到1.000.000的完美数字。一个完美数是指它的适当除数之和等于这个数本身。28是一个完美的数字,因为1+2+4+7+14=28。下面是我的代码

#include <iostream>
using namespace std;
int main() {
int a = 1000000;
for(int i = 1; i <= a; ++i)
{
    int sum = 0;
    int q; 
    // The biggest proper divisor is half the number itself
    if(i % 2 == 0) q = i/2;
    else q = (i+1)/2;

    for(int j = 1; j <= q; ++j)
    {
        if(i % j == 0) sum += j;
    }
    //Condition for perfect number
    if(sum == i) cout << i << " is a perfect number!" << endl;
}
system("pause");
return 0;
}

此代码中的哪些操作比较耗时?如何提高程序的速度?一般来说,我如何了解哪些操作是耗时的,以及如何避免这些操作?

真正了解哪些操作耗时且限制程序执行速度的唯一方法是通过探查器运行程序。这个工具会告诉你每秒钟的执行时间花在哪里(通常是在函数调用的基础上)。

具体地回答你的问题:这个程序中的大部分时间将花在这一行:

system("pause");

因为,除了这是一行可怕的代码之外,你应该去掉它,它实际上是用户输入,众所周知,椅子和屏幕之间的东西是减慢速度的原因。

您可以用以下内存消耗来交换计算:

const int max = 1000000;
std::vector<std::size_t> a(max);
for(std::size_t i = 1; i != a.size(); ++i) {
    for (std::size_t j = 2 * i; j < a.size(); j += i) {
        a[j] += i;
    }
}
for (std::size_t i = 1; i != a.size(); ++i) {
    if(a[i] == i) {
        std::cout << i << " is a perfect number!" << std::endl;
    }
}

实例

分支:if、循环、函数调用和goto成本高昂。它们往往会分散处理器执行数据传输和数学运算的注意力。

例如,您可以消除if语句:

q = (i + (i % 2)) / 2;  // This expression not simplified.

研究循环展开,尽管编译器可能会在更高的优化设置上执行此操作。

I/O操作成本高昂,尤其是使用格式化的I/O。试试这个:

if(sum == i)
{
  static const char text[] = " is a perfect number!n";
  cout << i;
  cout.write(text, sizeof(text) - 1); // Output as raw data.
}

除法和模运算代价高昂
如果可以除以2的幂,则可以将除法转换为右移
您可以通过使用二进制AND来避免模运算。

我的经验法则:

  • 条件分支(即比较)成本高昂
  • 除法代价高昂(以及模%)
  • 更喜欢整数运算而不是浮点运算

如何避免它们?

没有简单的答案。在很多情况下,你就是做不到。

您可以通过使用无分支表达式或改进程序逻辑来避免条件分支。

可以通过使用移位或查找表或重写表达式(如果可能)来避免除法。

通过模拟定点可以避免浮点运算。

在给定的示例中,您必须关注最内部循环的主体。这是执行频率最高的一行(约12500000000次,而其他行为1000000次)。不幸的是,存在着难以消除的比较和分歧。

对代码其他部分的优化不会产生可衡量的效果。特别是,不要担心cout语句:它总共会被调用4次。