【发布时间】:2016-05-06 06:47:36
【问题描述】:
我正在做一个项目,我将 RGB 转换为 luma,但 -mno-sse2 标志存在一些舍入问题:
这是测试代码:
#include <stdio.h>
#include <stdint.h>
static double rec709_luma_coeff[3] = {0.2126, 0.7152, 0.0722};
int main()
{
uint16_t n = 242 * rec709_luma_coeff[0] + 242 * rec709_luma_coeff[1] + 242 * rec709_luma_coeff[2];
printf("%u\n", n);
return 0;
}
这就是我得到的:
user@gentoo>gcc -mno-sse2 test.c -o test && ./test
241
user@gentoo> gcc test.c -o test && ./test
242
我想 gcc 对 double 乘法使用 sse2 优化,但我不明白为什么优化后的版本是正确的。
另外,您建议我使用什么来获得更一致的结果,ceil() 或 floor()?
【问题讨论】:
-
与优化无关。无 SSE2 意味着使用旧的 x87 FPU,它比 SSE2 更宽。从某种意义上说,x87 结果的精度更高,但结果可能与使用 SSE2 的结果不同
-
我建议
round()或nearbyint()而不是ceil()或floor()。前者的语义更可能是您想要的。此外,所有这些都可能在其不连续点附近出现一些不稳定,但对于round()和nearbyint(),它们以半整数出现,而对于ceil()和floor(),它们以整数出现。 -
@user3618511 为什么你首先使用双打进行色彩空间转换?这是史诗般的矫枉过正。
-
@user3618511 float 也太过分了
-
@user3618511 这种事情几乎总是用定点数学来完成。例如,
luma = (2126 * r + 7152 * g + 722 * b + 5000) / 10000。如果有什么更准确的(你可以让它与浮点数一起工作,但你实际上需要一些带有舍入偏差的黑客)。它也可以用 16 位二进制定点算法进行合理逼近,即使对于标量代码也更有效,并且无限容易与 SIMD 一起使用。
标签: c gcc compilation rounding sse2