【问题标题】:Why is std::pow(int, int) way faster than for loop with integer values?为什么 std::pow(int, int) 比带有整数值的 for 循环更快?
【发布时间】:2020-11-20 03:26:50
【问题描述】:

我和我的朋友写了一个计算多项式的程序:

P = abn + a2bn-1 + a3bn-2 + ... anb

他使用了 C++ std::pow(int, int) 函数,而我使用了两个 for 循环,因为我被教导使用整数的 for 循环比 std::pow(int, int) 函数更快,或者在最坏的情况下速度几乎相同!

他的代码:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    int a = 1,b = 1,n = 100000;
    long long P = 0;

    for(int i = 1, j = n; i <= n; i++, j--)
    {
        P += pow(a,i) * pow(b,j);
    }
    cout << P;
    return 0;
}

程序按预期返回 100000,执行时间:0.048 秒,第二次运行时为 0.049 秒

但是当我运行我的代码时:

#include <iostream>

using namespace std;

int main()
{
    int a = 1,b = 1,n = 100000;
    long long P = 0;

    for(int i = 1, j = n; i <= n; i++, j--)
    {
        int c = a, d = b;

        for (int k = 1; k < i; ++k) {

            c *= a;
        }

        for (int k = 1; k < j; ++k) {

            d *= b;
        }

        P += c * d;
    }
    cout << P;
    return 0;
}

程序再次返回预期的 100000,但执行时间为:17.039 秒,第二次运行时为 17.117 秒。

我的问题是,正如我一直被人们教导的那样,我在文章和教程中读到 std::pow(int, int) 要么会比带有整数的 for 循环慢,要么速度几乎相等,为什么如果我们将数字增加到 1000000,执行时间会有如此大的差异,我的代码甚至需要几分钟才能执行,而 pow(int, int) 函数代码会在几秒钟内执行。

【问题讨论】:

  • 你用的是什么编译器?你使用了哪些编译选项?
  • @PaulMcKenzie 我在 GNU GCC 编译器中使用了 Code::Blocks 20.03,所有其他选项都是编译器的默认选项
  • Code:Blocks 是 IDE,而不是编译器。正在使用什么版本的 g++?其次,您需要了解编译器选项,因为这将决定是否使用了优化。老实说,编译器的优化器会炸掉你写的那个循环,as shown here
  • @PaulMcKenzie 版本是 g++ (MinGW.org GCC-6.3.0-1) 6.3.0 因为我对 CS 很陌生 我不知道在哪里检查编译器选项,我如果您能帮助我,我将不胜感激,我也可以将选项发送给您!
  • @ShadeyyWasTaken -- 建议 -- 访问 Godbolt 网站,比较您的代码和您朋友的代码在生成的程序集方面的作用。通过指定-O2 打开优化。但外行人之所以说你朋友的代码更快,是因为你的朋友通过调用std::pow 将代码交到编译器手中,而你试图通过手动编写循环来在优化游戏中击败编译器。在那场比赛中,编译器几乎总是获胜。

标签: c++ loops for-loop execution-time pow


【解决方案1】:

这完全取决于std::pow 实现的质量,以及你的编译器的优化能力

例如,一些标准库将pow(x, y) 计算为exp(log(x)*y),即使对于整数指数,它也可能不准确且缓慢,从而导致此类问题

但一些更好的pow 实现会检查指数是否为整数以使用更好的算法。他们还使用exponentiating by squaring,因此它们将比您的线性乘法(如 for 循环)快很多。例如对于 b100000 他们只需要 17 个循环而不是 100000

如果编译器足够聪明,可以识别你的循环来计算功率,它可能会完全转换为std::pow。但可能不是你的情况,所以std::pow 仍然更快。如果您编写使用平方取幂的 pow(int, int) 函数,那么它可能比 std::pow 更快

【讨论】:

    猜你喜欢
    • 2013-05-22
    • 2023-04-09
    • 2017-04-25
    • 2018-01-04
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    相关资源
    最近更新 更多