我正在尝试做的是使用这个C代码并使用称为循环展开的技术对其进行优化,但在这种情况下我想使用四向循环展开。现在,我理解了这项技术,并且我理解了我不知道如何将其应用于此代码的概念。我是否需要添加一些额外的变量?在每个循环之后或者只是在所有循环结束时,我是否必须有一些代码?此代码是8x8块代码,用于处理像素并逆时针旋转90度。任何帮助将不胜感激。谢谢。
/*
* rotate8 - rotate with 8x8 blocking
*/
char rotate8_descr[] = "rotate8: rotate with 8x8 blocking";
void rotate8(int dim, pixel *src, pixel *dst)
{
int i, j, ii, jj;
for(ii = 0; ii < dim; ii += 8)
for(jj = 0; jj < dim; jj += 8)
for (i = ii; i < ii + 8; i++)
for (j = jj; j < jj + 8; j++)
dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}
答案 0 :(得分:5)
您可以使用8行显式代码替换内部循环
dst[RIDX(dim-1-jj, i, dim)] = src[RIDX(i, jj, dim)];
dst[RIDX(dim-1-(jj+1), i, dim)] = src[RIDX(i, (jj+1), dim)];
...
dst[RIDX(dim-1-(jj+7), i, dim)] = src[RIDX(i, (jj+7), dim)];
所以你要通过为每个值显式写一行来替换循环变量。
现在你可以重复下一个循环的8个值,你将有8 x 8行代码,依此类推。
除了理解练习之外,这对我来说似乎毫无意义,编译器非常有效地完成这些工作,他们会在合理的地方进行优化。手动滚动很少产生最佳代码。
答案 1 :(得分:4)
我想说一下它 - 然后我自己就这样做了。 令人惊讶的部分是 - 内部循环执行速度最快 布局 - 手动展开它实际上更慢。
然而 - 真正的问题是RIDX宏。切换内存布局并切换 外部循环具有重要的影响。
这是我最快的缩进版本,用于显示它与您的版本的不同之处。 假定RIDX宏是定义的。
#define RIDX(x,y,d) (x+(y)*(d))
typedef unsigned char pixel;
void rotate8(int dim, pixel *src, pixel *dst)
{
int i, j, ii, jj;
for(jj = 0; jj < dim; jj += 8)
for(ii = 0; ii < dim; ii += 8)
for (i = ii; i < ii + 8; i++)
for (j = jj; j < jj + 8; j++)
dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)];
}
...吸取的经验教训:始终剖析: - )
答案 2 :(得分:3)
gcc -funrull-loops
你不应该自己展开循环,除非GCC不能这样做(查看程序集)并且你已经通过使用分析器证明你必须加速这部分代码。
您拥有的示例代码看起来是自动循环展开的理想选择。
其他一些有用的标志:
-O3 // turns on a lot of optimizations (almost all) -ftree-vectorize -msse2 // vectorizes automatically some loops
答案 3 :(得分:0)
http://www.relisoft.com/book/lang/pointer/2ptrarr.html
如果您的编译器无法优化算法的人类可读,可维护版本,并且您必须加倍作为人类编译器 - 购买新的编译器!没人能买得起人类编制者了。所以,请怜悯自己和你的程序员,他们必须查看你的代码。