네온 내장 함수를 사용하여 최적화 된 코드로 C 코드를 변환하려고합니다.SSE 내장 함수에 해당하는 네온
operant의 벡터가 아닌 2 개의 operant를 조작하는 c 코드는 다음과 같습니다.
uint16_t mult_z216(uint16_t a,uint16_t b){
unsigned int c1 = a*b;
if(c1)
{
int c1h = c1 >> 16;
int c1l = c1 & 0xffff;
return (c1l - c1h + ((c1l<c1h)?1:0)) & 0xffff;
}
return (1-a-b) & 0xffff;
}
이 작업의 최적화 된 SEE 버전은 이미 구현 된 다음
#define MULT_Z216_NEON(a, b, out) \
temp = vorrq_u16 (*a, *b); \
// ??
// ??
*b = vsubq_u16(*out, *a); \
*b = vceqq_u16(*out, vdupq_n_u16(0x0000)); \
*b = vshrq_n_u16(*b, 15); \
*out = vsubq_s16(*out, *a); \
*a = vceqq_s16(*c, vdupq_n_u16(0x0000)); \
*c = vaddq_s16(*c, *b); \
*temp = vandq_u16(*temp, *a); \
*out = vsubq_s16(*out, *a);
난 :
#define MULT_Z216_SSE(a, b, c) \
t0 = _mm_or_si128 ((a), (b)); \ //Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b.
(c) = _mm_mullo_epi16 ((a), (b)); \ //low 16-bits of the product of two 16-bit integers
(a) = _mm_mulhi_epu16 ((a), (b)); \ //high 16-bits of the product of two 16-bit unsigned integers
(b) = _mm_subs_epu16((c), (a)); \ //Subtracts the 8 unsigned 16-bit integers of a from the 8 unsigned 16-bit integers of c and saturates
(b) = _mm_cmpeq_epi16 ((b), C_0x0_XMM); \ //Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or unsigned 16-bit integers in b for equality. (0xFFFF or 0x0)
(b) = _mm_srli_epi16 ((b), 15); \ //shift right 16 bits
(c) = _mm_sub_epi16 ((c), (a)); \ //Subtracts the 8 signed or unsigned 16-bit integers of b from the 8 signed or unsigned 16-bit integers of a.
(a) = _mm_cmpeq_epi16 ((c), C_0x0_XMM); \ ////Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or unsigned 16-bit integers in b for equality. (0xFFFF or 0x0)
(c) = _mm_add_epi16 ((c), (b)); \ // Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or unsigned 16-bit integers in b.
t0 = _mm_and_si128 (t0, (a)); \ //Computes the bitwise AND of the 128-bit value in a and the 128-bit value in b.
(c) = _mm_sub_epi16 ((c), t0); ///Subtracts the 8 signed or unsigned 16-bit integers of b from the 8 signed or unsigned 16-bit integers of a.
내가 거의 네온 내장 함수를 사용하여이 일을 변환했습니다 단지 _mm_mullo_epi16 ((a), (b));
과 _mm_mulhi_epu16 ((a), (b));
의 네온 등가물이 누락되었습니다. NEON에서 뭔가를 오해하고 있거나 그러한 내장 함수가 없습니다. NEONS 내장 함수를 사용하여 이러한 단계를 보관하는 것과 동일한 방법이 없다면?
UPDATE : 함수의 operants은 uint16x8_t NEON 벡터 (각 요소는 0과 65535 사이 uint16_t => 정수이다)이다 :
I는 이하의 점을 강조 깜빡했다. 어떤 사람이 내장 된 vqdmulhq_s16()
을 사용할 것을 제안했습니다. 곱셈 내장 함수는 벡터를 부호있는 값으로 해석하고 잘못된 출력을 생성하기 때문에이 함수의 사용은 주어진 구현과 일치하지 않습니다.
값이 32767 이상인 경우 아래에 제안 된 확대 곱하기 (vmull_u16)를 사용해야합니다. 값이 모두 32768보다 작 으면 vqdmulhq_s16을 사용할 수 있습니다. – BitBank