ARM의 고급 SIMD NEON 기능 활용

벡터화 컴파일러는 NEON 하드웨어 장치를 효율적으로 사용하여 C/C++ 코드를 병렬화할 수 있습니다. C 언어에는 병렬 동작을 지정하는 구문이 없지만 컴파일러에 다양한 힌트를 제공할 수 있습니다.

포인터 변수의 경우 정의할 때 "__restrict" 키워드를 추가할 수 있지만, 포인터가 가리키는 메모리 영역이 외부 포인터에 의해 참조 및 수정될 수 없도록 해야 합니다. 이는 포인터가 겹치는 영역을 처리하지 않도록 보장하는 효과가 있습니다. 기억의).

루프 수는 분명히 4 또는 8의 배수이며 컴파일러에서도 최적화를 위해 사용됩니다.

코드를 컴파일할 때 -O1 -ftree-Vectorize -mfpu=neon 옵션을 추가합니다.

샘플 코드:

#include <stdio.h>

int main(int argc, char *argv[])
{
	int arr[8] = {1,2,3,4,5,6,7,8};
	for(int i = 0; i < 8; i++) {
		arr[i] *= 3;
	}
	for(int i = 0; i < 8; i++) {
		printf("%d\n", arr[i]);
	}
	return 0;
}

분해(V로 시작하는 명령어는 NEON 명령어입니다):

00010408 <main>:
   10408:	e92d4070 	push	{r4, r5, r6, lr}
   1040c:	e24dd020 	sub	sp, sp, #32
   10410:	e1a0c00d 	mov	ip, sp
   10414:	e59fe05c 	ldr	lr, [pc, #92]	; 10478 <main+0x70>
   10418:	e8be000f 	ldm	lr!, {r0, r1, r2, r3}
   1041c:	e8ac000f 	stmia	ip!, {r0, r1, r2, r3}
   10420:	e89e000f 	ldm	lr, {r0, r1, r2, r3}
   10424:	e88c000f 	stm	ip, {r0, r1, r2, r3}
   10428:	f2c04053 	vmov.i32	q10, #3	; 0x00000003
   1042c:	f46d2adf 	vld1.64	{d18-d19}, [sp :64]
   10430:	f26229f4 	vmul.i32	q9, q9, q10
   10434:	f44d2adf 	vst1.64	{d18-d19}, [sp :64]
   10438:	eddd0b04 	vldr	d16, [sp, #16]
   1043c:	eddd1b06 	vldr	d17, [sp, #24]
   10440:	f26009f4 	vmul.i32	q8, q8, q10
   10444:	edcd0b04 	vstr	d16, [sp, #16]
   10448:	edcd1b06 	vstr	d17, [sp, #24]
   1044c:	e1a0400d 	mov	r4, sp
   10450:	e28d6020 	add	r6, sp, #32
   10454:	e59f5020 	ldr	r5, [pc, #32]	; 1047c <main+0x74>
   10458:	e4941004 	ldr	r1, [r4], #4
   1045c:	e1a00005 	mov	r0, r5
   10460:	ebffffa0 	bl	102e8 <printf@plt>
   10464:	e1560004 	cmp	r6, r4
   10468:	1afffffa 	bne	10458 <main+0x50>
   1046c:	e3a00000 	mov	r0, #0
   10470:	e28dd020 	add	sp, sp, #32
   10474:	e8bd8070 	pop	{r4, r5, r6, pc}
   10478:	000104f0 	.word	0x000104f0
   1047c:	00010510 	.word	0x00010510

Guess you like

Origin blog.csdn.net/konga/article/details/121727492