ARMv7 코어에서 이미지를 복사하려고합니다. 순진한 구현은 라인 당 memcpy를 호출하는 것입니다. 그래서 내 옆에 (여전히 매우 순진) 구현은 ~이었다빠른 ARM NEON memcpy
for (int i = 0; i < h; i++) {
uint8_t* dst = d;
const uint8_t* src = s;
int remaining = w;
asm volatile (
"1: \n"
"subs %[rem], %[rem], #32 \n"
"vld1.u8 {d0, d1, d2, d3}, [%[src],:256]! \n"
"vst1.u8 {d0, d1, d2, d3}, [%[dst],:256]! \n"
"bgt 1b \n"
: [dst]"+r"(dst), [src]"+r"(src), [rem]"+r"(remaining)
:
: "d0", "d1", "d2", "d3", "cc", "memory"
);
d += dp;
s += sp;
}
의 라인을 따라
for(i = 0; i < h; i++) {
memcpy(d, s, w);
s += sp;
d += dp;
}
내가 다음
d, dp, s, sp, w
정렬 모두 32 바이트 것을 알고 있었다 memcpy보다 150 % 더 빠른 반복 횟수 (다른 이미지에서 캐싱을 활용하지 않음)보다 빠릅니다. 내가 아직 프리 로딩을 사용하고 있기 때문에 최적의 위치 근처에 있지 않아야한다고 생각합니다.하지만 그렇게 할 때 성능이 현저히 떨어지는 것처럼 보입니다. 여기에 어떤 통찰력이 있습니까?
루프를 2 배 이상 풀어보세요. NEON로드는 파이프 라이닝 및 메모리 속도 때문에 즉시 발생하지 않습니다. 2 개의 상점과 2 개의 상점을 수행하는 경우, 이점을 확인해야합니다. 캐시 사전로드는 확실히 속도를 높일 수 있지만 미리 읽기 거리는 대상 플랫폼에 맞게 조정해야합니다. – BitBank
나는 그것을 시도했지만 그 차이는 무시할 정도였다. 나는 똑같은 추론을 따랐지만 그로드와 저장은 각각 2 사이클 밖에되지 않는다는 것을 명심하십시오. ([출처] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k /ch16s06s07.html)). 캐시 라인 크기는 64 바이트이고, 나는 64, 128, 192, 256 바이트를 먼저 프리 페치 (prefetching) 해 보았는데,이 모두가 상당히 느려졌다 (2-3 회). –
memcpy 소스를 보았습니까? 어쩌면 이미 최적화되었으며 해당 플랫폼에서 NEON 명령어를 사용합니다. –