我不认为你能比4条指令做得更好:2次洗牌和2次比较。
__m256d x = ...; // input
__m128d y = _mm256_extractf128_pd(x, 1); // extract x[2], and x[3]
__m128d m1 = _mm_max_pd(x, y); // m1[0] = max(x[0], x[2]), m1[1] = max(x[1], x[3])
__m128d m2 = _mm_permute_pd(m1, 1); // set m2[0] = m1[1], m2[1] = m1[0]
__m128d m = _mm_max_pd(m1, m2); // both m[0] and m[1] contain the horizontal max(x[0], x[1], x[2], x[3])
平凡的修改只有256位向量工作:
__m256d x = ...; // input
__m256d y = _mm256_permute2f128_pd(x, x, 1); // permute 128-bit values
__m256d m1 = _mm256_max_pd(x, y); // m1[0] = max(x[0], x[2]), m1[1] = max(x[1], x[3]), etc.
__m256d m2 = _mm256_permute_pd(m1, 5); // set m2[0] = m1[1], m2[1] = m1[0], etc.
__m256d m = _mm256_max_pd(m1, m2); // all m[0] ... m[3] contain the horizontal max(x[0], x[1], x[2], x[3])
(未经测试)
这是一个艰难的一...你只有1矢量这样做呢?或者你有许多载体需要找到最大值?你可以(相当)有效地做4个并行的4×4向量转置... – Mysticial 2012-03-20 22:28:55
@Mysticial:嗯......我正在处理很多向量。然而,处理的简单性并不能证明每次迭代都需要两次4x4转置操作。所以我正在处理一切“水平”而不需要换位。我以这种方式获得了极大的提速,接近4倍,因为我避免了转置的开销。一切都在手动展开4次的紧密循环中。但是,当循环结束时,我剩下最后一个AVX矢量。为了将结果存回到我的双精度标量值中,我必须找到其中最大的四个元素。因此,我的问题... – 2012-03-20 22:56:16
如果它不在“紧密的循环”,它甚至性能至关重要? – Mysticial 2012-03-20 22:59:05