2012-06-22 3 views
4

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 % 더 빠른 반복 횟수 (다른 이미지에서 캐싱을 활용하지 않음)보다 빠릅니다. 내가 아직 프리 로딩을 사용하고 있기 때문에 최적의 위치 근처에 있지 않아야한다고 생각합니다.하지만 그렇게 할 때 성능이 현저히 떨어지는 것처럼 보입니다. 여기에 어떤 통찰력이 있습니까?

+0

루프를 2 배 이상 풀어보세요. NEON로드는 파이프 라이닝 및 메모리 속도 때문에 즉시 발생하지 않습니다. 2 개의 상점과 2 개의 상점을 수행하는 경우, 이점을 확인해야합니다. 캐시 사전로드는 확실히 속도를 높일 수 있지만 미리 읽기 거리는 대상 플랫폼에 맞게 조정해야합니다. – BitBank

+0

나는 그것을 시도했지만 그 차이는 무시할 정도였다. 나는 똑같은 추론을 따랐지만 그로드와 저장은 각각 2 사이클 밖에되지 않는다는 것을 명심하십시오. ([출처] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k /ch16s06s07.html)). 캐시 라인 크기는 64 바이트이고, 나는 64, 128, 192, 256 바이트를 먼저 프리 페치 (prefetching) 해 보았는데,이 모두가 상당히 느려졌다 (2-3 회). –

+0

memcpy 소스를 보았습니까? 어쩌면 이미 최적화되었으며 해당 플랫폼에서 NEON 명령어를 사용합니다. –

답변

4

ARM은 이에 대한 훌륭한 기술 노트를 가지고 있습니다.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka13544.html

귀하의 성능은 마이크로 아키텍처에 따라 달라질 확실히 것이며, ARM의 노트는 A8에 있지만 나는 당신에게 괜찮은 아이디어를 줄 것이다 생각하고, 하단의 요약은의 좋은 토론이다 어떤 방법으로 인해 레지스터 사용량이 가장 적은지 등 일반 숫자를 뛰어 넘는 여러 가지 장단점이 있습니다.

그리고 또 다른 주석자가 언급 하듯이 프리 페칭은 올바르게 진행하기가 어렵습니다. 캐시의 크기와 각 라인의 크기 및 캐시 설계에 대한 다른 세부 사항에 따라 다른 마이크로 아키텍처와 다르게 작동합니다. 조심하지 않으면 필요한 라인을 터뜨릴 수 있습니다. 필자는 이식 가능한 코드를 피할 것을 권장합니다.