一些answers和讨论,甚至是boost::irangesource code都提到,在raw for循环上使用这些范围应该有性能上的损失。

但是,例如以下代码

#include <boost/range/irange.hpp>

int sum(int* v, int n) {
    int result{};
    for (auto i : boost::irange(0, n)) {
        result += v[i];
    }
    return result;
}

int sum2(int* v, int n) {
    int result{};
    for (int i = 0; i < n; ++i) {
        result += v[i];
    }
    return result;
}

我看不到生成的(-O3优化的)代码(Compiler Explorer)的差异。有谁看到一个示例,说明使用这样的整数范围可能会导致现代编译器中较差的代码生成?

编辑:显然,调试性能可能会受到影响,但这不是我的目的。
关于大步长(步长> 1)示例,我认为可能可以修改irange代码以更紧密地匹配大步长原始for循环的代码。

最佳答案



是。没有说明您的特定案例受到影响。但是将步骤更改为1以外的任何其他操作:

#include <boost/range/irange.hpp>

int sum(int* v, int n) {
    int result{};
    for (auto i : boost::irange(0, n, 8)) {
        result += v[i];           //^^^ different steps
    }
    return result;
}

int sum2(int* v, int n) {
    int result{};
    for (int i = 0; i < n; i+=8) {
        result += v[i];   //^^^ different steps
    }
    return result;
}

Live
尽管sum现在看起来更糟(循环没有展开),但sum2仍然受益于循环展开和SIMD优化。

编辑:

要评论您的编辑,确实是it might be possible to modify the irange code to more closely。但:
为了适应range-based for loops的扩展方式,boost::irange(0, n, 8)必须创建某种临时类型,实现begin / end迭代器和前缀operator++(显然不像int +=操作那么简单)。编译器正在使用模式匹配进行优化,这已进行了裁剪,以与标准C++和标准库一起使用。因此,irange的任何结果;如果它与编译器知道的优化模式略有不同,则优化不会启动。我认为,这就是库的作者提及性能损失的原因。

关于c++ - 在原始循环上使用boost::irange会降低性能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58855100/

10-16 07:32