我正在努力优化以下代码片段。正在为320x320x320体积中的每个体素调用该函数,其中每个体素是16位灰度值。体积被存储为一系列平面(横截面),并且每个平面是连续的1D阵列,因此例如当前体素下方的体素的位置变为currentPosition + pixelsPerRow并且其左侧的位置变为currentPosition-1。 / p>
该函数检查卷中的零交叉以及当前和相邻体素的绝对值是否高于特定阈值。这是Marr-Hildreth边缘探测器的必要部分。
currentPosition是当前体素,relativePosition也可以是当前体素(在这种情况下,在同一平面内围绕它的8个方向检查零交叉)或者它可以是直接在其上方或正下方的体素。这样,对于每个体素,执行27次检查,其覆盖3D中的所有可能方向。
也许可以重新排列函数,使其执行速度更快。我已经尝试以这样的方式安排检查顺序,即分支预测有更好的机会启动,但也许可以加快它的速度。目前,它需要50%的大型应用程序处理时间,因此需要进行一些优化。
bool zeroCrossing(int16_t* currentPosition, int16_t* relativePosition, int pixelsPerRow, int threshold)
{
return *currentPosition * *(relativePosition - pixelsPerRow - 1) < 0 && abs(*currentPosition + *(relativePosition - pixelsPerRow - 1)) > threshold
|| *currentPosition * *(relativePosition - pixelsPerRow) < 0 && abs(*currentPosition + *(relativePosition - pixelsPerRow)) > threshold
|| *currentPosition * *(relativePosition - pixelsPerRow + 1) < 0 && abs(*currentPosition + *(relativePosition - pixelsPerRow + 1)) > threshold
|| *currentPosition * *(relativePosition - 1) < 0 && abs(*currentPosition + *(relativePosition - 1)) > threshold
|| *currentPosition * *(relativePosition) < 0 && abs(*currentPosition + *(relativePosition)) > threshold
|| *currentPosition * *(relativePosition + 1) < 0 && abs(*currentPosition + *(relativePosition + 1)) > threshold
|| *currentPosition * *(relativePosition + pixelsPerRow - 1) < 0 && abs(*currentPosition + *(relativePosition + pixelsPerRow - 1)) > threshold
|| *currentPosition * *(relativePosition + pixelsPerRow) < 0 && abs(*currentPosition + *(relativePosition + pixelsPerRow)) > threshold
|| *currentPosition * *(relativePosition + pixelsPerRow + 1) < 0 && abs(*currentPosition + *(relativePosition + pixelsPerRow + 1)) > threshold;
}
答案 0 :(得分:1)
我的直觉是,这段代码非常适合并行化。使用AVX(2),或将其卸载到GPU。这将超出C ++的范畴,但对于程序的核心功能来说,这是合理的。
我假设您已经使用线程来并行化操作,因为这非常简单。请注意,使用AVX,您仍然需要线程;每个CPU核心都有自己的AVX单元。
答案 1 :(得分:0)
如果存在过零点,则会在两个相邻像素之间发生。在卷中运行时,您只需要检查每对邻居一次。如果您将函数应用于每个像素,则会检查每对像素两次。 (我也将像素这个术语用作3D图像的元素,我不喜欢体素这个术语。)
此外,您还可以检查共享边或顶点的像素对,只需要检查共享面的像素。如果下图中的像素a
和d
之间存在过零点,则a
和b
之间或a
和{{之间必须有一个过零点1}}。
c
因此,对于每个像素,您只需要检查三个邻居,而不是27.这会将执行时间减少到1/9。
但是,这并不能完全解释您的幅度检查,a b
c d
和a
之间的差异可能大于其他两个邻居之间的差异。但是,我不认为这很重要。
就此而言,您的幅度检查错误:如果d
和a
符号不同且非常大(一个重要的过零点),则b
可能为0,你不会数它。你可能想要与众不同!