2016-10-20 14 views
0

__m256i 레지스터가 있고 각 64 비트 그룹에서 4 개의 하위 32 비트를 추출하여 압축하여 메모리에 연속 저장합니다. 즉, __m256i 레지스터에 8 개의 32 비트 단어가 들어있는 경우 {a0, a1, a2, a3, a4, a5, a6, a7}, {a0, a2, a4, a6} 네 개의 단어를 연속적으로 메모리에 저장하려고합니다.AVX 레지스터에서 대체 하위 32 비트 추출 및 저장

는 다음 코드를 내놓았다 : 내가 올바른 생각하면

void mystore(uint32 *dst, const __m256i& src) 
{ 
     __m256 ps256 = _mm256_castsi256_ps(src); 
     __m128 lo128 = _mm256_extractf128_ps(ps256, 0); 
     __m128 hi128 = _mm256_extractf128_ps(ps256, 1); 
     __m128 pack128 = _mm_shuffle_ps(lo128, hi128, 0 + (2<<2) + (0<<4) + (2<<6)); 
     __m128i r = _mm_castps_si128(pack); 
    _mm256_storeu_si256(reinterpret_cast<__m128i*>(dst), r) 
} 

가, 캐스팅 작업이 단지 컴파일러 유형 검사를 만족시키기 위해 존재하지만, 그들은 있도록 동등한 효과가없는 조합에 총 대기 시간 비용은 셔플 명령어 및 2 추출 명령어에 대해 3이고, 정렬되지 않은 저장소의 비용을 더한 것입니다.

더 빠른 방법이 있나요?

감사

+1

'_mm256_extractf128_ps은 (ps256, 0);'도 단지 캐스트입니다. 모든 YMM 레지스터의 하위 절반은 해당 XMM 레지스터로 액세스 할 수 있으며, 다행스럽게도 컴파일러는이를 알고 있으며, 올바른 _m_cast_intrainsic이 최적의 asm을보다 직접 표현하는 대신 extract (v, 0)를 작성하는 것에 대해 우리를 처벌하지 않습니다. (마찬가지로 컴파일러는 실제 PEXTRD 대신'_mm_extract_epi32 (v, 0)'을 쓸 때 MOVD를 사용합니다. –

+0

흥미 롭다, 나는 그것을 몰랐다. – Fabio

답변

2

당신은 같은 것을 사용 시도 할 수 있습니다 :

const __m256i K_PERM = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7); 

inline void mystore(uint32_t * dst, const __m256i & src) 
{ 
    __m256i permuted = _mm256_permutevar8x32_epi32(src, K_PERM); 
    __m128i lo128 = _mm256_extractf128_si256(permuted, 0); 
    _mm_storeu_si128((__m128i*)dst, lo128); 
} 
+0

permute 명령어는 대기 시간이 3이므로 위의 설명에 따르면 기존 솔루션보다 비용이 많이 드는 것으로 보입니다. 그럼에도 불구하고 나는 그것에게 시험을 줄 것이다. – Fabio

+1

주 제한 사항은 메모리 대역폭 (두 변형 모두)이라고 생각합니다. – ErmIg