簡體   English   中英

使用AVX指令實現_mm256_permutevar8x32_ps

[英]implement _mm256_permutevar8x32_ps using AVX instructions

AVX2內在_mm256_permutevar8x32_ps可以在通道上執行混洗,這對於排序長度為8的數組非常有用。

現在我只有AVX(Ivy Bridge)並希望在最小周期內做同樣的事情。 請注意,數據和索引在編譯時都是輸入和未知的。

例如,數組為[1,2,3,4,5,6,7,8] ,指數為[3,0,1,7,6,5,2,4] ,輸出應為[4,1,2,8,7,6,3,5]

大多數方便的內在函數的控制掩碼必須是常量(沒有“var”后綴),因此在這種情況下不適合。

提前致謝。

要在AVX中跨越通道進行置換,您可以在通道內進行置換,然后使用_mm256_permute2f128_ps來交換通道,然后進行混合。 例如。 假設您要將數組{1,2,3,4,5,6,7,8}更改為{0,0,1,2,3,4,5,6}。 你可以這樣做

__m256 t0 = _mm256_permute_ps(x, _MM_SHUFFLE(1, 0, 3, 2));
__m256 t1 = _mm256_permute2f128_ps(t0, t0, 41);
__m256 y = _mm256_blend_ps(t0, t1, 0x33);

_mm256_permute2f128_ps具有歸零功能 ,這非常有用(另請參閱“ 英特爾本能指南在線” )。 我在上面的代碼中使用它來將第一個通道交換到第二個通道然后將第一個通道歸零。 有關更多詳細信息,請參閱shift-sse-avx-registers-32-bits-left-and-while-shift-in-zero

編輯:permutevar內在函數允許運行時置換,因此不限於編譯時間常量。 下面的代碼是來自Agner Fog的Vector Class Librarylookup8函數。

static inline Vec8f lookup8(Vec8i const & index, Vec8f const & table) {
#if INSTRSET >= 8 && VECTORI256_H > 1 // AVX2
#if defined (_MSC_VER) && _MSC_VER < 1700 && ! defined(__INTEL_COMPILER)        
    // bug in MS VS 11 beta: operands in wrong order. fixed in 11.0
    return _mm256_permutevar8x32_ps(_mm256_castsi256_ps(index), _mm256_castps_si256(table)); 
#elif defined (GCC_VERSION) && GCC_VERSION <= 40700 && !defined(__INTEL_COMPILER) && !defined(__clang__)
        // Gcc 4.7.0 has wrong parameter type and operands in wrong order. fixed in version 4.7.1
    return _mm256_permutevar8x32_ps(_mm256_castsi256_ps(index), table);
#else
    // no bug version
    return _mm256_permutevar8x32_ps(table, index);
#endif

#else // AVX
    // swap low and high part of table
    __m256  t1 = _mm256_castps128_ps256(_mm256_extractf128_ps(table, 1));
    __m256  t2 = _mm256_insertf128_ps(t1, _mm256_castps256_ps128(table), 1);
    // join index parts
    __m256i index2 = _mm256_insertf128_si256(_mm256_castsi128_si256(index.get_low()), index.get_high(), 1);
    // permute within each 128-bit part
    __m256  r0 = _mm256_permutevar_ps(table, index2);
    __m256  r1 = _mm256_permutevar_ps(t2,    index2);
    // high index bit for blend
    __m128i k1 = _mm_slli_epi32(index.get_high() ^ 4, 29);
    __m128i k0 = _mm_slli_epi32(index.get_low(),      29);
    __m256  kk = _mm256_insertf128_ps(_mm256_castps128_ps256(_mm_castsi128_ps(k0)), _mm_castsi128_ps(k1), 1);
    // blend the two permutes
    return _mm256_blendv_ps(r0, r1, kk);
#endif
}

以下是get_lowget_high函數:

Vec2db get_low() const {
    return _mm256_castpd256_pd128(ymm);
}
Vec2db get_high() const {
    return _mm256_extractf128_pd(ymm,1);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM