【发布时间】:2015-11-06 13:20:50
【问题描述】:
我有“荣幸”改善以下其他人的代码的运行时间。 (这是来自精明算法的非最大抑制”)。我的第一个想法是使用 SSE 内在代码,我在这方面很新,所以我的问题是。
有没有机会这样做? 如果是这样,有人可以给我一些提示吗?
void vNonMaximumSupression(
float* fpDst,
float const*const fpMagnitude,
unsigned char const*const ucpGradient, ///< [in] 0 -> 0°, 1 -> 45°, 2 -> 90°, 3 -> 135°
int iXCount,
int iXOffset,
int iYCount,
int ignoreX,
int ignoreY)
{
memset(fpDst, 0, sizeof(fpDst[0]) * iXCount * iXOffset);
for (int y = ignoreY; y < iYCount - ignoreY; ++y)
{
for (int x = ignoreX; x < iXCount - ignoreX; ++x)
{
int idx = iXOffset * y + x;
unsigned char dir = ucpGradient[idx];
float fMag = fpMagnitude[idx];
if (dir == 0 && fpMagnitude[idx - 1] < fMag && fMag > fpMagnitude[idx + 1] ||
dir == 1 && fpMagnitude[idx - iXCount + 1] < fMag && fMag > fpMagnitude[idx + iXCount - 1] ||
dir == 2 && fpMagnitude[idx - iXCount] < fMag && fMag > fpMagnitude[idx + iXCount] ||
dir == 3 && fpMagnitude[idx - iXCount - 1] < fMag && fMag > fpMagnitude[idx + iXCount + 1]
)
fpDst[idx] = fMag;
else
fpDst[idx] = 0;
}
}
}
【问题讨论】:
-
这种不统一的方向让人讨厌。是否可能运行相同的目录?
-
@harold:可以使用
ucpGradient来查找随机掩码以获取该向量槽的正确元素吗?可能不会,因为获取 4 个源元素可能需要从 6 个数组元素中读取。 -
我认为这里有一个微妙的错误,如果最多两个邻居值具有完全相同的大小:没有一个大于它的邻居,所以两者都会被抑制。我相信这两个比较中的任何一个都应该是
<=/>=。 -
我认为将其转换为 SIMD 代码的“标准”方法是执行所有 8 次比较(如果您可以重用之前像素的比较结果,则为 4 次),并为每个像素计算一个结果每个方向,然后使用
dir屏蔽掉不需要的结果。每个像素需要 4 次比较操作而不是两次,但是如果您可以在一条指令中执行 4 或 8 次比较操作,它可能仍然会更快。 -
@nikie:是的,这是标准的“做所有分支”方法,它需要 8 次比较而不是两次。它的行为与 GPU 的自然端口一样=)鉴于浮点的 SSE 是 4 宽,尚不清楚这种矢量化代码是否会比标量代码更快。
标签: c++ computer-vision sse edge-detection canny-operator