我有一个相对较大的循环,并希望展开它以加快我的应用程序。代码是:
byte* oRow = (byte*)bitmapData1.Scan0 + (y * bitmapData1.Stride);
for (UINT x = 0; x < 4000; ++x)
{
#pragma unroll
byte grey = (
(oRow[x + x + x] * 114) + //B
(oRow[x + x + x + 1] * 587) + //G
(oRow[x + x + x + 2] * 299)) / 1000; //R
fl_x = floor(x + x);
fl_y = floor(y + y);
cl_x = fl_x + 1;
if (cl_x >= 4752)
cl_x = fl_x;
cl_y = fl_y + 1;
if (cl_y >= 3168)
cl_y = fl_y;
fractionX = x + x - fl_x;
fractionY = y + y - fl_y;
oneMinusX = 1.0 - fractionX;
oneMinusY = 1.0 - fractionY;
b1 = oneMinusX * grey + fractionX * grey;
b2 = oneMinusX * grey + fractionX * grey;
blue = oneMinusY * (b1)+fractionY * (b2);
b1 = oneMinusX * grey + fractionX * grey;
b2 = oneMinusX * grey + fractionX * grey;
green = oneMinusY * (b1)+fractionY * (b2);
b1 = oneMinusX * grey + fractionX * grey;
b2 = oneMinusX * grey + fractionX *grey;
red = oneMinusY * (b1)+fractionY * (b2);
oRow[x + x + x] = blue;
oRow[x + x + x + 1] = green;
oRow[x + x + x + 2] = red;
}
我尝试通过将循环计数器更改为
来展开它for (UINT x = 0; x < 2000; x+=2)
并在重复代码之前将x添加到x,但它运行不正常
答案 0 :(得分:4)
我尝试通过将循环计数器更改为
来展开它
for (UINT x = 0; x < 2000; x+=2)
并在重复代码之前将x添加到x,但它运行不正常
循环展开的逻辑是有缺陷的。您需要在每次迭代时处理x
和x + 1
的元素,而不是x
和x + 2000
,并且上限仍然是4000:
for (UINT x = 0; x < 4000; x+=2)
{
// do stuff for element x
// ...
// do stuff for element x + 1
// ...
}
正如已经注意到的那样,你可能会浪费你的时间。编译器非常擅长在需要时展开代码,手动循环展开甚至可以在现代CPU上适得其反。
专业提示:确保您正在编译并启用所有优化功能(例如gcc -O3 ...
),并对您的代码进行分析,以确保此循环确实需要优化。如果您确定需要优化此代码,那么在使用循环展开之前,您可以使用一些非常明显的低效率。
答案 1 :(得分:1)
for (UINT x = 0; x < 2000; x+=2)
将循环1000个值:0,2,4 ... 1998
这可能不是你想要的。你要么
for (UINT x = 0; x < 2000; x+=1) // values 0, 1, ... 1999
或
for (UINT x = 0; x < 4000; x+=2) // values 0, 2, ... 3998