c++ - 如何使用 SSE 优化矩阵 3 乘 3 的点?

标签 c++ optimization sse matrix-multiplication

我必须在我的图像的每个点上应用一个变换矩阵来获得新的点坐标。

为此,我创建了一个自定义 Matrix3by3 类,其中包含一个大小为 9 的 float 组。

为了将矩阵应用到每个点,我首先创建了这个函数:

constexpr auto apply_matrix(const Matrix3by3 & m, const Vec2i & p) -> Vec2f
{
  const auto x = m.at(0, 0) * p.x + m.at(0, 1) * p.y + m.at(0, 2);
  const auto y = m.at(1, 0) * p.x + m.at(1, 1) * p.y + m.at(1, 2);
  const auto z = m.at(2, 0) * p.x + m.at(2, 1) * p.y + m.at(2, 2);

  return { x / z, y / z };
}

如您所见,此函数将执行简单的矩阵乘法而不进行最后一次乘法,因为我的 2D 图像中没有 z 值。

这很好用,但由于这部分代码是热代码,我正在尝试优化它,所以我创建了它的 SSE 版本:

constexpr auto apply_matrix(const Matrix3by3 & m, const Vec2i & p) -> Vec2f
{
  using SSEVec3 = union {
    struct
    {
      float z, y, x;

    };
    __m128 values_ = _mm_setzero_ps();
  };

  const auto mvec1 = _mm_set_ps(0, m.at(0, 0), m.at(0, 1), m.at(0, 2));
  const auto mvec2 = _mm_set_ps(0, m.at(1, 0), m.at(1, 1), m.at(1, 2));
  const auto mvec3 = _mm_set_ps(0, m.at(2, 0), m.at(2, 1), m.at(2, 2));

  const auto pvec1 = _mm_set1_ps(static_cast<float>(p.x));
  const auto pvec2 = _mm_set1_ps(static_cast<float>(p.y));

  auto result = SSEVec3{};
  result.values_ = _mm_add_ps(_mm_add_ps(_mm_mul_ps(mvec1, pvec1), _mm_mul_ps(mvec2, pvec2)), mvec3);

  return { result.x / result.z, result.y / result.z };
}

这也行,但比第一个版本慢,而且由于我正在学习 SSE,所以我不明白为什么会这样。

我对第二个版本的想法是并行计算 x、y 和 z 值。

那么,这就是我的问题,为什么 SSE 版本较慢,我如何优化它以使其尽可能快?

谢谢!

最佳答案

一般来说,只优化需要优化的部分,而不是您认为需要优化的部分。

可能是(原始)代码中最糟糕的一点,而您的“优化”根本没有帮助,就是重复的划分。除 float 或 double 远比此代码中的其他所有内容差,因此您最好的优化是通过计算 1/z(将 一次)计算为辅助变量,然后乘以两次来减少它结果。

但是 - 如开头所述 - 您可能不需要任何优化,或者您可能需要其他优化。测试、剖析并寻找最慢的一段代码。猜测通常会导致浪费精力和不必要的代码复杂性。

关于c++ - 如何使用 SSE 优化矩阵 3 乘 3 的点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45517086/

相关文章:

优化相关的C程序条件语句

linux - gcc 4.x 不支持 x87​​ FPU 数学?

c++ - boost::asio::ip::address::from_string 在无效地址上没有抛出异常

python - Numpy/pandas 优化 : bins counting

c - 正在检查编译器优化的循环中的复杂表达式?

c++ - 模拟 AVX-512 掩码指令

simd - 如何使用avx(但没有avx-512)将int 64转换为int 32

c++ - 来自 Boost.org 的 Boost Log 1.65.0 示例的链接错误

c++ - 细粒度访问说明符 C++

c++ - 将用户模式 ​​dll 中的高级函数映射到 NTDLL.dll