>백엔드 개발 >C++ >AVX2 및 BMI2 명령어는 마스크를 기반으로 왼쪽 패킹을 어떻게 효율적으로 구현할 수 있습니까?

AVX2 및 BMI2 명령어는 마스크를 기반으로 왼쪽 패킹을 어떻게 효율적으로 구현할 수 있습니까?

Susan Sarandon
Susan Sarandon원래의
2024-12-29 19:34:11246검색

How Can AVX2 and BMI2 Instructions Efficiently Implement Left Packing Based on a Mask?

마스크를 기준으로 왼쪽 포장을 위한 효율적인 AVX2 구현

SSE와 달리 AVX에는 마스크를 기준으로 왼쪽 포장에 대한 전용 지침이 없습니다. 그러나 AVX2 및 BMI2 명령어의 조합을 사용하면 이 작업을 효율적으로 수행할 수 있습니다.

AVX2 및 BMI2 사용

이 접근 방식은 vpermps(_mm256_permutevar8x32_ps) 명령어를 활용합니다. 차선 교차 가변 셔플을 수행하는 pdep (_pdep_u64) 비트 단위 추출을 제공하는 BMI2의 명령입니다.

알고리즘 단계

  1. 원하는 순열을 나타내는 압축된 3비트 인덱스로 상수를 만듭니다.
  2. pdep을 사용하여 마스크.
  3. 인덱스를 바이트당 하나로 압축 해제합니다.
  4. 압축 해제된 인덱스를 vpermps용 제어 마스크로 변환합니다.
  5. vpermps를 사용하여 변수 셔플을 수행합니다.

구현 세부 정보

아래 코드는 AVX2 BMI2의 구현을 제공합니다.

#include <immintrin.h>

__m256 compress256(__m256 src, unsigned int mask)
{
  uint64_t expanded_mask = _pdep_u64(mask, 0x0101010101010101);  // unpack each bit to a byte
  expanded_mask *= 0xFF;    // mask |= mask<<1 | mask<<2 | ... | mask<<7;
  // ABC... -> AAAAAAAABBBBBBBBCCCCCCCC...: replicate each bit to fill its byte

  const uint64_t identity_indices = 0x0706050403020100;    // the identity shuffle for vpermps, packed to one index per byte
  uint64_t wanted_indices = _pext_u64(identity_indices, expanded_mask);

  __m128i bytevec = _mm_cvtsi64_si128(wanted_indices);
  __m256i shufmask = _mm256_cvtepu8_epi32(bytevec);

  return _mm256_permutevar8x32_ps(src, shufmask);
}

성능 분석

이 구현에서는 16c에서 6 uops가 발생합니다. 숨어 있음. 잠재적으로 4주기당 1회 반복의 처리량을 유지하여 여러 반복을 계속 진행할 수 있습니다.

대체 접근 방식

Zen 3 이전 AMD CPU의 경우 pext/pdep 속도가 매우 느리므로 대체 접근 방식이 더 나을 수 있습니다. 16비트 요소의 경우 128비트 벡터 접근 방식을 사용할 수 있습니다. 8비트 요소의 경우 여러 개의 겹치는 청크를 포함하는 다른 기술을 사용할 수 있습니다.

위 내용은 AVX2 및 BMI2 명령어는 마스크를 기반으로 왼쪽 패킹을 어떻게 효율적으로 구현할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.