一些answers和讨论,甚至是boost::irange
的source 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/