我不認爲你能比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