16

我正在尝试使用 SSE 找到 4x4 矩阵 (M) 与向量 (u) 乘法的最有效实现。我的意思是 Mu = v。

据我了解,有两种主要方法可以解决此问题:

    method 1) v1 = dot(row1, u), v2 = dot(row2, u), v3 = dot(row3, u), v4 = dot(row4, u)
    method 2) v = u1 col1 + u2 col2 + u3 col3 + u4 col4.

方法 2 在 SSE2 中很容易实现。方法 1 可以使用 SSE3 中的水平加指令或 SSE4 中的点积指令来实现。但是,在我所有的测试中,方法 2 总是优于方法 1。

我认为方法 1 具有优势的一个地方是 3x4 矩阵,例如仿射变换。在这种情况下,最后一个点积是不必要的。但即使在这种情况下,4x4 矩阵上的方法 2 也比 3x4 矩阵上的方法 1 更快。我发现在 4x4 矩阵上比方法 2 更快的唯一方法是在 4x3 矩阵上的方法 2。

那么水平加法和点积指令有什么意义呢?事实上,在这种情况下,点生成指令的性能最差。也许它与数据的格式有关?如果无法定义矩阵的排序方式,那么转置是必要的,在这种情况下,方法 1 可能会更好?

请参阅下面的一些代码。

__m128 m4x4v_colSSE(const __m128 cols[4], const __m128 v) {
  __m128 u1 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(0,0,0,0));
  __m128 u2 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(1,1,1,1));
  __m128 u3 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(2,2,2,2));
  __m128 u4 = _mm_shuffle_ps(v,v, _MM_SHUFFLE(3,3,3,3));

  __m128 prod1 = _mm_mul_ps(u1, cols[0]);
  __m128 prod2 = _mm_mul_ps(u2, cols[1]);
  __m128 prod3 = _mm_mul_ps(u3, cols[2]);
  __m128 prod4 = _mm_mul_ps(u4, cols[3]);

  return _mm_add_ps(_mm_add_ps(prod1, prod2), _mm_add_ps(prod3, prod4));
}

__m128 m4x4v_rowSSE3(const __m128 rows[4], const __m128 v) {
  __m128 prod1 = _mm_mul_ps(rows[0], v);
  __m128 prod2 = _mm_mul_ps(rows[1], v);
  __m128 prod3 = _mm_mul_ps(rows[2], v);
  __m128 prod4 = _mm_mul_ps(rows[3], v);

  return _mm_hadd_ps(_mm_hadd_ps(prod1, prod2), _mm_hadd_ps(prod3, prod4));
}

__m128 m4x4v_rowSSE4(const __m128 rows[4], const __m128 v) {
  __m128 prod1 = _mm_dp_ps (rows[0], v, 0xFF);
  __m128 prod2 = _mm_dp_ps (rows[1], v, 0xFF);
  __m128 prod3 = _mm_dp_ps (rows[2], v, 0xFF);
  __m128 prod4 = _mm_dp_ps (rows[3], v, 0xFF);

  return _mm_shuffle_ps(_mm_movelh_ps(prod1, prod2), _mm_movelh_ps(prod3, prod4),  _MM_SHUFFLE(2, 0, 2, 0));
}  
4

1 回答 1

10

水平加法和点积指令很复杂:它们被分解为多个更简单的微操作,这些微操作就像简单的指令一样由处理器执行。将水平加法和点积指令精确分解为微操作是特定于处理器的,但对于最近的英特尔处理器,水平加法被分解为 2 个 SHUFFLE + 1 个 ADD 微操作,而点积被分解为 1 个 MUL + 1 个 SHUFFLE + 2 个 ADD 微操作。除了大量的微操作之外,这些指令还强调了处理器流水线中的指令解码器:英特尔处理器每个周期只能解码一条这样的复杂指令(与 4 条简单指令相比)。在 AMD Bulldozer 上,这些复杂指令的相对成本甚至更高。

于 2013-02-20T02:50:09.067 回答