我有一个库,它有一些图像处理算法,包括感兴趣区域(裁剪)算法。使用GCC进行编译时,自动矢量化器会加速大量代码,但会降低Crop算法的性能。是否有一种标记某个循环的方法可以被矢量化器忽略,或者是否有更好的方法来构造代码以获得更好的性能?
for (RowIndex=0;RowIndex<Destination.GetRows();++RowIndex)
{
rowOffsetS = ((OriginY + RowIndex) * SizeX) + OriginX;
rowOffsetD = (RowIndex * Destination.GetColumns());
for (ColumnIndex=0;ColumnIndex<Destination.GetColumns();++ColumnIndex)
{
BufferSPtr=BufferS + rowOffsetS + ColumnIndex;
BufferDPtr=BufferD + rowOffsetD + ColumnIndex;
*BufferDPtr=*BufferSPtr;
}
}
其中
SizeX
是源的宽度
OriginX
是感兴趣区域的左侧
OriginY
是感兴趣区域的顶端
答案 0 :(得分:0)
我没有找到任何关于更改循环的优化标志的内容,但是根据文档,您可以在函数上使用属性optimize
(查看here和here)要覆盖该函数的优化设置,如下所示:
void foo() __attribute__((optimize("O2", "inline-functions")))
如果您想为多个功能更改它,可以使用#pragma GCC optimize
为所有后续功能(look here)设置它。
因此,您应该能够使用不同的优化标志集编译包含裁剪的函数,省略自动向量化。这样做的缺点就是硬编码该函数的编译标志,但这是我找到的最好的。
关于重组以获得更好的表现,我想到在评论中已经提到的两点(假设范围不能重叠):
将指针声明为__restrict
,告诉编译器它们没有别名(一个指针所指向的区域不会被函数内的任何其他方式访问)。指针别名的可能性是优化器的主要障碍,因为如果它不知道写入BufferD
是否会改变BufferS
的内容,它就不能轻易地重新排序访问。
通过调用copy来替换内部循环:
std::copy(BufferS + rowOffsetS, BufferS + rowOffsetS + Destination.GetColumns(), BufferD + rowOffsetD);
copy
函数可能已经过很好的优化(可能会将参数转发给memmove
),这样可以使代码更快,同时也可以缩短代码(总是加分)。