에 대한 감사합니다 다음은 큰 배열의 최소 및 최대를 찾기 위해 어떻게 최적화 된 예이다. 이 함수는 크기가 128보다 작 으면 단순히 반환합니다.
/*
* minmax.S
*
* Created on: 2014. 10. 29.
* Author: Jake Lee
*/
// unsigned int minmax(unsigned char *pSrc, unsigned int size);
.text
.arm
.global minmax
pSrc .req r0
size .req r1
qmin1 .req q0
dmina .req d0
dminb .req d1
qmax1 .req q1
dmaxa .req d2
dmaxb .req d3
qmin2 .req q2
qmax2 .req q3
.align 5
.func
minmax:
subs size, size, #128
bxmi lr
vmov.i8 qmin1, #0xff
vmov.i8 qmax1, #0
vmov.i8 qmin2, #0xff
vmov.i8 qmax2, #0
.align 5
1:
vld1.8 {q8, q9}, [pSrc]!
vld1.8 {q10, q11}, [pSrc]!
vld1.8 {q12, q13}, [pSrc]!
vld1.8 {q14, q15}, [pSrc]!
subs size, size, #128
pld [pSrc, #64*3]
pld [pSrc, #64*4]
vmin.u8 qmin1, q8
vmax.u8 qmax1, q8
vmin.u8 qmin2, q9
vmax.u8 qmax2, q9
vmin.u8 qmin1, q10
vmax.u8 qmax1, q10
vmin.u8 qmin2, q11
vmax.u8 qmax2, q11
vmin.u8 qmin1, q12
vmax.u8 qmax1, q12
vmin.u8 qmin2, q13
vmax.u8 qmax2, q13
vmin.u8 qmin1, q14
vmax.u8 qmax1, q14
vmin.u8 qmin2, q15
vmax.u8 qmax2, q15
bpl 1b
// deal width residuals (size % 128)
cmp size, #-128
addgt pSrc, pSrc, size
bgt 1b
// shrink to sixteen
vmin.u8 qmin1, qmin2
vmax.u8 qmax1, qmax2
// shrink to eight
vpmin.u8 dmina, dmina, dminb
vpmax.u8 dmaxa, dmaxa, dmaxb
// shrink to four
vpmin.u8 dmina, dmina, dminb
vpmax.u8 dmaxa, dmaxa, dmaxb
// shrink to two
vpmin.u8 dmina, dmina, dminb
vpmax.u8 dmaxa, dmaxa, dmaxb
// shrink to one
vpmin.u8 dmina, dmina, dminb
vpmax.u8 dmaxa, dmaxa, dmaxb
vmov r0, dmina[0]
vmov r1, dmaxa[0]
and r0, r0, #0xff
and r1, r1, #0xff
orr r0, r0, r1, lsl #16
bx lr
.endfunc
.end
반환 값은 부호없는 int입니다. 단지 약간만 수정,
result = minmax(pSrc, size);
min = result & 0xff;
max = result >> 16;
infocenter.arm.com에서 어셈블리 설명서를 다운로드 할 수 있습니다. 그런 다음 'vmin'및 'vmax'지침을 볼 수 있습니다. –
귀하의 의견을 보내 주셔서 감사합니다. 나는 vmin과 vmax를 알고 있지만 두 개의 레지스터에서 각 레인을 비교합니다. 그렇다면 최소값과 최대 값을 쌍으로 설정해야하지만 모든 값을 초과하지는 마십시오. – Zoli
3 개의 연속적인 vpmin과 vpmax가 나머지 작업을 수행합니다. 그러나 명령어 대기 시간이 성능을 심각하게 저하 시키므로 ARM 정수 코어로이 작업을 수행하는 것이 좋습니다. NEON은 이러한 작은 데이터를 우선 처리하지 않습니다. –