alf*_*lfC 11 c++ for-loop clang-tidy
我试图理解这个铿锵有力的警告:altera-id-dependent-backward-branch这似乎是由这个循环触发的。
for(; first != current; ++first)
Run Code Online (Sandbox Code Playgroud)
我的例子是这段代码,它看起来几乎完全是std::uninitialized_fill_n.
静态分析器抱怨说:
error: backward branch (for loop) is ID-dependent due to variable reference to 'current' and may cause performance degradation [altera-id-dependent-backward-branch,-warnings-as-errors]
for(; current != first; ++first) {
Run Code Online (Sandbox Code Playgroud)
uninitialized_fill_n(ForwardIt first, Size n, T const& v) {
ForwardIt current = first;
try {
for(; n > 0; ++current, --n) {
new (std::addressof(*current)) T(v);
}
return current;
} catch(...) {
for(; first != current; ++first) { // clang-tidy error here
std::addressof(*first)->~T();
}
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了不同的方法来重写代码(例如向后循环),以抑制此警告,但我做不到。
是否有一种标准方法可以以可以接受的方式重写后备(catch)循环altera-id-dependent-backward-branch?
我在用clang-tidy 13.0.0。
我还在我的代码库中发现了相同警告的另一个实例(这是由 Howard Hinnart 编写的哈希函数的实现):
auto fnv1a(void const* key, std::size_t len, std::size_t h) noexcept {
auto const *p = static_cast<unsigned char const*>(key);
unsigned char const* const e = p + len;
for(; p < e; ++p) { // warning here
h = (h ^ *p) * 1099511628211U; // prime
}
return h;
}
Run Code Online (Sandbox Code Playgroud)
小智 3
该altera-id-dependent-backward-branch警告源自 clang-tidy 的 FPGA 特定规则。具体来说,当针对 FPGA 时,编译器将 C++ 转换为硬件,而硬件与传统 CPU 相比具有不同的性能特征。
您看到的警告是因为循环中的分支取决于归纳变量(current在第一种情况和p第二种情况下)。将循环综合到硬件中时,依赖于归纳变量的分支可能会导致更长的管道停顿。确切的影响是特定于硬件的,但对于高性能循环,影响可能并不小。
为了解决该警告,循环的终止条件需要独立于归纳变量。
让我们从第一个例子开始:
for(; first != current; ++first) { // clang-tidy error here
std::addressof(*first)->~T();
}
Run Code Online (Sandbox Code Playgroud)
您可以提前确定迭代次数,然后使用固定循环界限:
auto distance = std::distance(first, current);
for(auto i = 0; i < distance; ++i, ++first) {
std::addressof(*first)->~T();
}
Run Code Online (Sandbox Code Playgroud)
对于第二个例子:
for(; p < e; ++p) { // warning here
h = (h ^ *p) * 1099511628211U; // prime
}
Run Code Online (Sandbox Code Playgroud)
您可以将其重写为:
auto distance = e - p;
for(std::size_t i = 0; i < distance; ++i, ++p) {
h = (h ^ *p) * 1099511628211U; // prime
}
Run Code Online (Sandbox Code Playgroud)
此转换确保循环边界是固定的并且不依赖于归纳变量。因此,FPGA 合成器应该能够更轻松地创建高效的流水线。
也就是说,您应该始终测试综合结果以验证性能是否满足您的期望。根据特定的硬件和循环的复杂性,可能仍然存在性能权衡。
| 归档时间: |
|
| 查看次数: |
1302 次 |
| 最近记录: |