自动矢量化感兴趣区域(裁剪)
Posted
技术标签:
【中文标题】自动矢量化感兴趣区域(裁剪)【英文标题】:Auto vectorization Region of interest (crop) 【发布时间】:2012-09-18 12:46:45 【问题描述】:我有一个库,其中包含一些图像处理算法,包括感兴趣区域(裁剪)算法。使用 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
是感兴趣区域的顶部
【问题讨论】:
我不确定我是否正确理解了您的问题。您想将该循环标记为不被矢量化或重组它以获得更好的性能?对我来说似乎很矛盾。但在性能方面:这两个范围可以重叠吗?如果不是:您是否在指针上使用__restrict
以使编译器清楚这一点? Pointeraliasing 是优化的一大亮点。此外:您是否考虑过将std::copy
用于您的内部循环?这可能会得到更好的优化,并使您的代码更短。
这似乎是一个矛盾,但这就是想法。向量化目前会降低性能,因此我可以想到为此循环禁用它或改进代码是两个选项!我会限制并复制一下。
您可能想在您的问题中提到,在这种情况下,作物的表现会恶化。就目前而言,我假设 Crop 算法的性能通过矢量化保持不变。如果您还不知道,-ftree-vectorizer-verbose=n
标志可能会帮助您获得关于优化器在做什么以及为什么做的更具体的信息。
【参考方案1】:
我还没有找到任何关于更改循环优化标志的信息,但是根据文档,您可以在函数上使用属性 optimize
(查看 here 和 here)来覆盖优化设置这个函数有点像这样:
void foo() __attribute__((optimize("O2", "inline-functions")))
如果您想为多个功能更改它,您可以使用#pragma GCC optimize
为以下所有功能设置它(look here)。
因此,您应该能够使用一组不同的优化标志编译包含裁剪的函数,省略自动矢量化。这具有硬编码该函数的编译标志的缺点,但这是我发现的最好的。
关于重组以获得更好的性能,我已经在 cmets 中提到了两点(假设范围不能重叠):
将指针声明为__restrict
以告诉编译器它们没有别名(一个指针指向的区域不会被函数内的任何其他方式访问)。指针别名的可能性是优化器的主要绊脚石,因为如果它不知道写入BufferD
是否会改变BufferS
的内容,它就不能轻易地重新排序访问。
用复制调用替换内部循环:
std::copy(BufferS + rowOffsetS, BufferS + rowOffsetS + Destination.GetColumns(), BufferD + rowOffsetD);
copy
函数可能已经过很好的优化(可能会将参数转发给memmove
),这样可以使您的代码更快,同时也可以使您的代码更短(总是一个加分项)。
【讨论】:
使用复制会禁用此循环的自动矢量化并且提供比我之前更好的性能。谢谢!以上是关于自动矢量化感兴趣区域(裁剪)的主要内容,如果未能解决你的问题,请参考以下文章