이 모든 것이 간단하지는 않습니다.
순진한 접근 방식은 간단히 인덱스를 얻는 것으로 시작됩니다 (비트 마스크로 0 1 2 3 4 5 6 7
및 vand
의 정적 벡터로드). 그러나, 출력 벡터의 한쪽 끝에서 - 그것들이 나타내는 입력 레인과는 다른 차선에서 그것들을 모으기 위해서 - 당신은 임의의 순열 연산을 필요로합니다. 벡터를 임의로 치환 할 수있는 명령은 하나 뿐이며 vtbl
(또는 vtbx
, 본질적으로 같은 것)입니다. 그러나 vtbl
은 대상 순서의 소스 인덱스 벡터를 사용하며 이는 생성하려고하는 것과 정확히 동일합니다. 따라서 최종 결과를 산출하기 위해서는 최종 결과를 사용해야하므로 비효율적 인 효율적인 솔루션은 불가능합니다. QED.
기본적으로 문제는 벡터를 정렬하는 것인데, 본질적으로 병렬 SIMD 작업이 아닙니다. NEON은 미디어 처리를 위해 설계된 병렬 SIMD 명령어 세트이며보다 일반적인 벡터 처리의 데이터 종속/수평/분산 수집 작업에 대해서는 실제로 제외되지 않습니다.
포인트를 증명하기 위해 순수한 NEON에서 스칼라 코드를 전혀 사용하지 않고 관리했습니다. 끔찍한입니다. 가장 좋은 "하나 또는 두 개의 비트 시프트 NEON 명령어"는 몇 가지 조건부 선택 기반 회전 비트 마스크 누적 트릭킹입니다. 이 명확하지 않으면, 나는 그것이 무엇을 (example)를 따라 디버거 또는 시뮬레이터를 통해 스테핑 좋을 것 :
// d0 contains input vector
vmov.u8 d1, #0
vmov.u8 d2, #0
vmvn.u8 d3, #0
vdup.u8 d4, d0[0]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[1]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[2]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[3]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[4]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[5]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[6]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vsub.u8 d1, d1, d3
vdup.u8 d4, d0[7]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
vbic.u8 d1, d1, d3
// d1 contains output vector
부정 행위와 반대 방향으로 d0
회전 필요로 루프를 (사용하여 우리가 할 수있는 그러한 이 작은 수) d0[0]
을 통해 각 원래 차선에 접근하지만, 정말 덜 끔찍하지 :
vmov.u8 d1, #0
vmov.u8 d2, #0
vmvn.u8 d3, #0
mov r0, #8
1:
vdup.u8 d4, d0[0]
vext.u8 d5, d2, d3, #7
vbit.u8 d3, d5, d4
subs r0, r0, #1
vext.u8 d0, d0, d0, #1
vsub.u8 d1, d1, d3
bne 1b
vbic.u8 d1, d1, d3
를 이상적으로,이 벡터의 상수가 아닌 순열을 필요 피하기 위해 알고리즘의 다른 부분을 재 작업 모두 가능하다면, 어떻게 그 대신에.
이 문제는 나에게 [비교 결과에 따라 왼쪽 패킹]을 상기시킵니다. (http://stackoverflow.com/questions/36932240/avx2-what-is-the-most-efficient-way-to-pack-left 기반 마스크). 비교 결과에 따라 왼쪽 패킹 셔플 마스크를 생성하는 기존 기술이있는 경우 모두 설정됩니다. 내 AVX2 + BMI2 대답은 정수 비트 마스크 (MOVMSKPS에서 : 각 벡터 요소에서 한 비트, 일반적으로 비교 결과에 유용)와 함께 x86의'pext' 비트 필드 추출 명령을 사용합니다. –
PEXT가 없다면 (ARM은 이에 해당하지 않는다고 가정), 사용할 수있는 다른 SIMD 왼쪽 포장 방법이 있습니다. 아,하지만 더 신중하게 읽고, 그 슬라이드는 그냥 LUT에서 셔플 마스크를로드 생각합니다.64 비트 레인 당 8 바이트를 사용하면 64 비트 입력마다 256 개의 입력 LUT 룩업이 가능합니다 (ARM은 벡터 비교/테스트를 효율적으로 수행 할 수 있고 비교 결과를 정수 배열 인덱스로 사용하기위한 비트 마스크로 변환 할 수 있다고 가정) –
@ PeterCordes - _ "비교 결과에 따라 왼쪽 패킹 셔플 마스크를 생성 할 수있는 기존 기술이 있다면 모두 해결할 수 있습니다. 바로 여기에서 달성하려는 것입니다. 가능한 임의 셔플 링 명령은 문제를 재귀 적으로 만 만들어주기 때문에 도움이되지 않습니다. – Notlikethat