【问题标题】:FizzBuzz Optimisation | Modulus vs Decrement Operator PerformanceFizzBu​​zz 优化 |模数与递减运算符性能
【发布时间】:2021-01-16 10:00:17
【问题描述】:

这不是 FizzBu​​zz 代码中关于如何处理重复的 if 语句的典型辩论。我认为这是个人喜好问题。

我是来问关于重复数学运算的选择的。

通常,FizzBu​​zz 代码的解决方案是在每次迭代中使用取模运算符。但是,我担心它对性能的影响。

据我所知,模数运算符与除法运算符紧密相连,与简单的增量和减量运算符相比,它具有相当大的性能开销。

另外,我不相信编译器有能力分析和优化循环中模运算符的使用。

因此,我给出了仅使用简单递减运算符的替代解决方案。以下代码是用 C++ 编写的。

我希望了解我的方法是否会带来性能优势,或者它是否真的是一个糟糕的想法会降低性能。

如果还有其他方法可以进一步优化 FizzBu​​zz 代码。 (我认为在经过修改的 FizzBu​​zz 拼图中有很多案例可供比较,查找表可能更可取)


典型的 FizzBu​​zz 解决方案。

for (unsigned int i = 1; i <= 1000000; ++i) {
    if (!(i % 15))
        std::cout << "FizzBuzz\n";
    else if (!(i % 3))
        std::cout << "Fizz\n";
    else if (!(i % 5))
        std::cout << "Buzz\n";
    else
        std::cout << i << '\n';
}

我的优化代码。

static const unsigned int fa {3};
static const unsigned int fb {5};

unsigned int a {fa};
unsigned int b {fb};

for (unsigned int i = 1; i <= 1000000; ++i) {
    --a, --b;
    if (!a && !b) {
        a = fa;
        b = fb;
        std::cout << "FizzBuzz\n";
    } else if (!a) {
        a = fa;
        std::cout << "Fizz\n";
    } else if (!b) {
        b = fb;
        std::cout << "Buzz\n";
    } else {
        std::cout << i << '\n';
    }
}

【问题讨论】:

  • 如果您正在使用 FizzBu​​zz 进行工作面试的编码评估,我建议您不要提交您的“优化代码”。它看起来很模糊且难以维护。
  • 恕我直言,这个问题更适合Code Review SE
  • @JHBonarius 别担心,这不是求职面试。我最近刚遇到 FizzBu​​zz,它引起了我的兴趣。
  • 顺便说一句,你总是可以假设很多关于(微)优化的。但唯一知道的方法是测量。我建议你学习Google Test Framework 之类的东西,这样你就可以使用QuickBench
  • 看起来与quickbench相当(使用std::stringstream而不是std::cout和下限以避免时间限制)。

标签: c++ performance optimization fizzbuzz


【解决方案1】:

在模数情况和减量情况下,运行时间将由流输出支配。即使不考虑 I/O,条件(很难预测)也会比算术贡献更多。最后,整数除法或模数除以常数非常快,因为它是通过特殊的乘法例程而不是 DIV 来实现的。

在某些情况下,用有条件设置的计数器替换模数会更快。这种情况不是其中之一。

【讨论】:

  • 条件句(预测不好) 这是什么意思?为什么条件句比算术贡献更多?
  • 恕我直言,这更像是一个评论而不是一个答案
  • @DesmondRhodes 现代 CPU 在执行分支(例如循环和 if 语句)方面效率低下,除非这些分支遵循某些极其简单的模式。见stackoverflow.com/questions/11227809/…
  • @JHBonarius 不,这是对 OP 关于该方法是否会提供性能优势的问题的直接回答。
  • false, false, true 似乎是一个简单的模式 ;-)
猜你喜欢
  • 2012-04-20
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 2012-02-21
  • 2018-07-18
  • 2012-11-04
相关资源
最近更新 更多