I';我试图使用4路循环展开来优化这个c代码
我想做的是使用一种叫做循环展开的技术对C代码进行优化,但在本例中,我想使用四向循环展开。现在,我理解了技术,也理解了概念,我只是不知道如何将它应用到这段代码中。我必须添加一些额外的变量吗?我是否需要在每个循环之后或者仅仅在所有循环的末尾都有一些代码?此代码是8x8块代码,用于获取像素并将其逆时针旋转90度。任何帮助都将不胜感激。多谢各位I';我试图使用4路循环展开来优化这个c代码,c,C,我想做的是使用一种叫做循环展开的技术对C代码进行优化,但在本例中,我想使用四向循环展开。现在,我理解了技术,也理解了概念,我只是不知道如何将它应用到这段代码中。我必须添加一些额外的变量吗?我是否需要在每个循环之后或者仅仅在所有循环的末尾都有一些代码?此代码是8x8块代码,用于获取像素并将其逆时针旋转90度。任何帮助都将不胜感激。多谢各位 /* * rotate8 - rotate with 8x8 blocking */ char rotate8_descr[] = "rotate8:
/*
* 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)];
}
/*
*rotate8-使用8x8块旋转
*/
char rotate8_descr[]=“rotate8:使用8x8块旋转”;
无效旋转8(整数尺寸,像素*src,像素*dst)
{
int i,j,ii,jj;
对于(ii=0;ii
您可以用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行代码,依此类推
除了理解练习之外,这对我来说似乎毫无意义,编译器做这类事情非常有效,他们会在有意义的地方进行优化。手动滚动很少产生最佳代码
gcc -funrull-loops
gcc-funrull循环
除非GCC无法展开循环(查看程序集),否则您不应该自己展开循环,并且您已经使用探查器证明必须加快这部分代码的速度
您的示例代码看起来是自动循环展开的完美候选
其他一些有用的标志:
-O3 // turns on a lot of optimizations (almost all)
-ftree-vectorize -msse2 // vectorizes automatically some loops
-O3//开启了许多优化(几乎全部)
-ftree vectorize-msse2//自动向量化某些循环
我想说,但后来我自己也这么做了。 令人惊讶的是,内部循环的执行速度最快,完全符合您的要求 布局-手动展开实际上比较慢 然而,真正的问题是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)];
}
定义RIDX(x,y,d)(x+(y)*(d))
typedef无符号字符像素;
无效旋转8(整数尺寸,像素*src,像素*dst)
{
int i,j,ii,jj;
对于(jj=0;jj如果您的编译器无法优化人类可读、可维护的算法版本,并且您必须兼任人类编译器,请购买一个新的编译器!没有人再买得起人工编译器了。所以,可怜你自己和你的程序员同事吧,他们将不得不看你的代码你可能想修正语法高亮吗?你把它描述成一个问题吗?也可以考虑使用更多的描述性的名字,如“顶部,底部,左边,右边”,而不是“i,ii,j,jj”。很难理解。两个内部循环可能通过使用UInt64和位移位来提高速度。为什么在问题的末尾加上[闭合]?这并不意味着“已回答”…+1我建议使用OP配置文件来分析他的代码,看看瓶颈在哪里,然后反汇编他的代码,看看编译器是如何处理瓶颈的。