时间:2019-02-12 标签:c++sseintrinsicsatan2
c++ SSE intrinsics atan2
我需要一个非常快的 atan2 来从 sobel 值中获取梯度(我正在实施 canny edge 算法。)。有谁知道一个非常快速的实现,最好是内在函数(SIMD)或一个非常快速的近似。 (我认为一个近似值就足够了,因为这些值四舍五入为 0°、45°、90°、135°)
提前致谢
ADD:我知道英特尔在 SVML 中的 IPP atan2,不幸的是我不能使用它。
您似乎想四舍五入到一个八分圆数,大概是从 -22.5°
到 337.5°
,增量为 45°
。
八分圆通过方程
通过原点的四条线分隔
Y = X tan(Θ),
或
a.Y - b.X = 0.
具有 suitable 个比例因子。
通过计算四个所需角度的这些表达式的符号,您将找到八分圆。通过巧妙的组合,您可以将符号评估限制为三个,因为有 8=2³
种可能性。
很可能可以使用 SIMD 指令通过计算判别表达式、它们的符号和它们符号的 suitable 组合来对此进行评估,但这并非微不足道。
可能不需要转换为 45° 的倍数,甚至不需要顺序编号。这完全取决于您如何处理八分圆信息。
其他 SIMD 建议:
使用预加载系数,您可以使用 16 位整数运算(可能使用乘加法)一次性计算出 (X, Y) 对的所有四个直线方程。然后得到标志并用_mm_movemask_epi8
将它们打包成四位。使用四位值作为小型查找的输入 table.
如 GCC 内联汇编中所述 here atan2()
is already a single FPU instruction: x87 FPU opcode FPATAN
. Just look at the disassembly your compiler generates when you call std::atan2()
. If it is not that single FPU instruction, then you can try this:
inline double my_atan2 (double y, double x) {
double result;
asm (
"fpatan\n\t"
: "=t" (result) // outputs; t = top of fpu stack
: "0" (x), // inputs; 0 = same as result
"u" (y) // u = 2nd floating point register
);
return result;
}
我需要一个非常快的 atan2 来从 sobel 值中获取梯度(我正在实施 canny edge 算法。)。有谁知道一个非常快速的实现,最好是内在函数(SIMD)或一个非常快速的近似。 (我认为一个近似值就足够了,因为这些值四舍五入为 0°、45°、90°、135°)
提前致谢
ADD:我知道英特尔在 SVML 中的 IPP atan2,不幸的是我不能使用它。
您似乎想四舍五入到一个八分圆数,大概是从 -22.5°
到 337.5°
,增量为 45°
。
八分圆通过方程
通过原点的四条线分隔Y = X tan(Θ),
或
a.Y - b.X = 0.
具有 suitable 个比例因子。
通过计算四个所需角度的这些表达式的符号,您将找到八分圆。通过巧妙的组合,您可以将符号评估限制为三个,因为有 8=2³
种可能性。
很可能可以使用 SIMD 指令通过计算判别表达式、它们的符号和它们符号的 suitable 组合来对此进行评估,但这并非微不足道。
可能不需要转换为 45° 的倍数,甚至不需要顺序编号。这完全取决于您如何处理八分圆信息。
其他 SIMD 建议:
使用预加载系数,您可以使用 16 位整数运算(可能使用乘加法)一次性计算出 (X, Y) 对的所有四个直线方程。然后得到标志并用_mm_movemask_epi8
将它们打包成四位。使用四位值作为小型查找的输入 table.
如 GCC 内联汇编中所述 here atan2()
is already a single FPU instruction: x87 FPU opcode FPATAN
. Just look at the disassembly your compiler generates when you call std::atan2()
. If it is not that single FPU instruction, then you can try this:
inline double my_atan2 (double y, double x) {
double result;
asm (
"fpatan\n\t"
: "=t" (result) // outputs; t = top of fpu stack
: "0" (x), // inputs; 0 = same as result
"u" (y) // u = 2nd floating point register
);
return result;
}