作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个函数来创建高斯滤波器(使用 Armadillo 库),它可以是 2D 或 3D,具体取决于它接收到的输入的维数。这是代码:
template <class ty>
ty gaussianFilter(const ty& input, double sigma)
{
// Our filter will be initialized to the same size as our input.
ty filter = ty(input); // Copy constructor.
uword nRows = filter.n_rows;
uword nCols = filter.n_cols;
uword nSlic = filter.n_elem / (nRows*nCols); // If 2D, nSlic == 1.
// Offsets with respect to the middle.
double rowOffset = static_cast<double>(nRows/2);
double colOffset = static_cast<double>(nCols/2);
double sliceOffset = static_cast<double>(nSlic/2);
// Counters.
double x = 0 , y = 0, z = 0;
for (uword rowIndex = 0; rowIndex < nRows; rowIndex++) {
x = static_cast<double>(rowIndex) - rowOffset;
for (uword colIndex = 0; colIndex < nCols; colIndex++) {
y = static_cast<double>(colIndex) - colOffset;
for (uword sliIndex = 0; sliIndex < nSlic; sliIndex++) {
z = static_cast<double>(sliIndex) - sliceOffset;
// If-statement inside for-loop looks terribly inefficient
// but the compiler should take care of this.
if (nSlic == 1){ // If 2D, Gauss filter for 2D.
filter(rowIndex*nCols + colIndex) = ...
}
else
{ // Gauss filter for 3D.
filter((rowIndex*nCols + colIndex)*nSlic + sliIndex) = ...
}
}
}
}
如我们所见,在最内层的循环中有一个 if 语句,它检查第三维(nSlic)的大小是否等于 1。一旦在函数的开头计算,nSlic 将不会改变它的值,所以编译器应该足够聪明来优化条件分支,我不应该损失任何性能。
但是...如果我从循环中删除 if 语句,我将获得性能提升。
if (nSlic == 1)
{ // Gauss filter for 2D.
for (uword rowIndex = 0; rowIndex < nRows; rowIndex++) {
x = static_cast<double>(rowIndex) - rowOffset;
for (uword colIndex = 0; colIndex < nCols; colIndex++) {
y = static_cast<double>(colIndex) - colOffset;
for (uword sliIndex = 0; sliIndex < nSlic; sliIndex++) {
z = static_cast<double>(sliIndex) - sliceOffset;
{filter(rowIndex*nCols + colIndex) = ...
}
}
}
}
else
{
for (uword rowIndex = 0; rowIndex < nRows; rowIndex++) {
x = static_cast<double>(rowIndex) - rowOffset;
for (uword colIndex = 0; colIndex < nCols; colIndex++) {
y = static_cast<double>(colIndex) - colOffset;
for (uword sliIndex = 0; sliIndex < nSlic; sliIndex++) {
z = static_cast<double>(sliIndex) - sliceOffset;
{filter((rowIndex*nCols + colIndex)*nSlic + sliIndex) = ...
}
}
}
}
在使用 g++ -O3 -c -o main.o main.cpp
编译并测量两种代码变体的执行时间后,我得到以下结果:
(1000 次重复,大小为 2048 的二维矩阵)
如果在里面:
如果在外面:
如果 nSlic 的值甚至没有改变,为什么编译器不优化分支?我必须重组代码以避免 for
循环中的 if
语句?
最佳答案
在循环中有一个额外的变量会影响寄存器的使用,这可能会影响时序,即使分支预测工作正常。您需要查看生成的程序集才能知道。它还可能影响难以检测的缓存命中率。
关于c++ - 为什么我不是分支预测的受害者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34278437/
在build.gradle中配置受害者插件时出现错误。 Gradle版本是2.0。 buildscript { repositories { mavenRepo url: "h
我是一名优秀的程序员,十分优秀!