矩阵的反转不准确

时间:2017-11-17 13:21:54

标签: c math matrix floating-point sse

我正在尝试编写测试以验证矩阵的逆,但是当我使用 FLT_EPSILON 来比较结果时,测试失败。

比较功能如下所示:test_assert_mat4_eq

我要做的是:

A = random matrix (4x4 float matrix)
B = inv(A)
C = inv(B)

assert(A == C) <---- fails

首先让我解释一下我如何计算矩阵逆; mat4是4x4浮点矩阵,如果启用SIMD,则矩阵的逆将通过SIMD指令(SSE2和AVX)计算。

如果SSE2已启用,您可以在glm_mat4_inv看到矩阵反码,然后通过glm_mat4_inv_sse2计算逆,同时还有glm_mat4_inv_precise_sse2版本,以避免 _mm_rcp_ps < / strong>指令。我使用第二个(glm_mat4_inv_precise_sse2)版本进行测试。

assert_true(fabsf(m1[i][j] - m2[i][j]) <= 0.0001);

传递我的macbook但它仍然在Linux上失败。

assert_true(fabsf(m1[i][j] - m2[i][j]) <= FLT_EPSILON);这甚至不会传递给macos。也许与0.001相比也适用于linux,但精度太低。

我还在glm repo(https://github.com/g-truc/glm/issues/700)上创建了一个问题,因为这个问题对glm也有效。

这有什么问题?为什么精度太低?这个可以吗?我应该这样离开(通过删除测试或改变精度)?

注意:使用test_rand_mat4函数生成随机矩阵。但我只是用它来生成一个矩阵。我没有在任何地方使用任何随机矩阵,所有矩阵都是仿射变换矩阵,也许我应该使用仿射变换(这是主要目的)进行比较

2 个答案:

答案 0 :(得分:3)

  1. 4⨉4矩阵足够小,您可以检测代码以打印每个计算步骤后涉及的每个浮点数,然后比较macOS和Linux结果以查看它们的不同之处。 (使用C %a中的printf格式打印十六进制浮点数或使用%.30g之类的内容来打印十进制的整个值。)

  2. 告诉我们差异超过.0001是没有意义的,因为我们不知道你的数据是多少。通常,数字误差将与所涉及的一些数字的大小成比例。

  3. 如果在使用IEEE-754浮点的硬件上运行的macOS和Linux上执行“相同”操作,则应该实现相同的结果。因此,任何差异都可能是因为您没有使用相同的操作。这种差异的原因可能包括两个系统使用不同的源代码(例如,因为一个使用SIMD,因为SSE已启用,另一个使用标量代码)或编译器正在以不同方式编译代码。暂时覆盖SSE决策,以便在两个系统上测试相同的源代码。调试完成后,如果可能,在两个系统上测试SSE代码。之后,将SSE代码与非SSE代码进行比较。

  4. 您应该从简单的测试用例开始,而不是使用随机数据进行测试,并开始处理更多涉及的测试用例。从身份矩阵开始。简单的情况有助于调试基本逻辑,而不会涉及明显的浮点错误。然后修改元素以生成更复杂的案例。生成用于测试的矩阵时,请避免ill-conditioned matrices。我在生成用于测试矩阵逆的矩阵方面没有经验,因此您将不得不研究如何修改矩阵以改善其条件数,或者其他人可能会提出建议。

  5. 不要通过调用inv两次来测试矩阵逆。这会错过简单的错误,例如复制和粘贴错误,导致名为inv的例程实际上是矩阵副本或否定。相反,使用矩阵逆的已知良好参考实现或使用已知测试用例(单位矩阵的逆是单位矩阵,其他可以构造)或使用逆的其他属性(将逆乘以原始矩阵)应该产生单位矩阵)。使用double作为测试代码。在4×4矩阵求逆中发现错误所需的测试用例数量不足以使性能变得重要。

答案 1 :(得分:0)

我仔细检查了测试代码,测试代码中出现了复制粘贴错误。矩阵反函数中使用 _mm_rcp_ps 指令来提高性能。问题是我希望在 _mm_rcp_ps 版本和非 _mm_rcp_ps 版本的测试中具有相同的精度。我已经修好了测试。

现在assert_true(fabsf(m1[i][j] - m2[i][j]) <= 0.0000009f);在macOS和Linux上都传递了精确/准确的版本

assert_true(fabsf(m1[i][j] - m2[i][j]) <= 0.0009f)在macOS和Linux上都通过了快速( _mm_rcp_ps )版本。

相同的测试也传递给travis-ci。

另一方面,它不起作用,因为我使用了完全随机的矩阵,即使随机比例也不会因为病态矩阵而起作用(感谢@Eric Postpischil和@geza)