2013-02-14 3 views
2

NEON의 12 개의 쿼드 레지스터를로드하는 간단한 asm 코드가 있으며, 이중 명령어 기능을 사용하기 위해로드 명령어와 함께 pairwise add 명령어를 병행했습니다. 여기 코드를 확인했습니다 하나는 볼 수 있듯이예상보다 많은 사이클을 소비하는 Neon VLD?

http://pulsar.webshaker.net/ccc/sample-d3a7fe78

이 코드는 약 13주기를하고있다. 그러나 보드에 코드를로드 할 때로드 명령은로드 당 1 사이클 이상 걸리는 것으로 보입니다. VPADAL이 명시된대로 1 사이클을 수행하지만 VLD1이 1 사이클 이상 걸리는 것으로 확인되었습니다. 왜 그런가요?

것은 나는 다음과 같은 신세를지고 있습니다 :

  1. 주소가 16 바이트로 정렬됩니다.
  2. 장소에서, 명령어 프리로드 명령 pld [r0, #192] 시도 vld1.64 {d0, d1} [r0,:128]!
  3. 에 정렬 힌트를 제공했지만 그 대신 실제로 대기 시간을 줄이는주기에 추가 할 것 같다.

누군가 내가 뭘 잘못하고 있는지 말해 줄 수 있습니까? 왜이 대기 시간입니까?

기타 사항 :

는 코텍스 A8
  • 아암 2009q1 크로스 컴파일러 툴 체인
  • 을 참조
    • 어셈블리 코딩에 코드로 인해 예상되는 것보다 훨씬 느리게 실행
  • +0

    더 많은 현실을 반영합니까? http://pulsar.webshaker.net/ccc/beta-sample-d3a7fe78 ('베타'시뮬레이터 사용) –

    +0

    @AkiSuihkonen, 어떻게 가능합니까? VPADAL과 VLD는 병렬로 실행할 수 있어야하고, 제시 한 시뮬레이터 링크와 유사하지 않으며 NEON이 왜 그렇게 늦게 시작해야합니까? – nguns

    +0

    한 번에로드가 완료 될 것으로 예상합니까? 거리 (l1, l2, 동적 램)에 따라 많은 사이클이 소요됩니다. 처음로드를 실행 한 다음 추가 할 경우 많은 이점이 있다고 생각합니다. – auselen

    답변

    1

    현재 쓰여지고있는 것처럼, 파이프 라인 노점의 완벽한 폭풍을 일으키고 있습니다. 파이프 라인 아키텍처를 사용하는 모든 최신 CPU에서 지침은 이상적인 조건에서 한 주기로 실행될 수 있습니다. 이상적인 조건은 명령이 메모리를 기다리지 않고 레지스터 종속성이 없다는 것입니다. 코드를 작성한 방식으로는 메모리에서 읽는 데 지연이없고 읽기 결과에 따라 다음 명령을 내릴 수 없습니다. 이것은 최악의 성능을 유발합니다. 또한, 왜 여러 레지스터에 pairwise 추가 누적하는지 잘 모르겠습니다. 다음과 같이 시도하십시오.

    veor.u16 q12,q12,q12  @ clear accumulated sum 
    top_of_loop: 
        vld1.u16 {q0,q1},[r0,:128]! 
        vld1.u16 {q2,q3},[r0,:128]! 
        vpadal.u16 q12,q0 
        vpadal.u16 q12,q1 
        vpadal.u16 q12,q2 
        vpadal.u16 q12,q3 
        vld1.u16 {q0,q1},[r0,:128]! 
        vld1.u16 {q2,q3},[r0,:128]! 
        vpadal.u16 q12,q0 
        vpadal.u16 q12,q1 
        vpadal.u16 q12,q2 
        vpadal.u16 q12,q3 
        subs r1,r1,#8 
        bne top_of_loop 
    

    추가를 실행하기 전에로드 명령어의 수를 달리하여 실험하십시오. 요점은 대상 레지스터를 사용하기 전에 읽기가 발생하는 시간을 허용해야한다는 것입니다.

    참고 : Q4-Q7을 사용하면 비 휘발성 레지스터이므로 위험합니다. 안드로이드에서는 이러한 것들 (특히 Q4)에 임의의 쓰레기가 표시됩니다.

    +0

    답변을 주셔서 감사합니다. 보드에서 코드를 확인했으며 코드가 4 번로드 된 후 64bytes 이상의 요청 (즉, cortex-a8에서 하나의 캐시 라인)이 발생하는 것으로 보입니다. 그 이유는 아직 없습니다. 따라서'vld'로드 요청 직후의 'vpadal'은 문제가되지 않습니다. 나는 당신의 코드와 소년을 시험해 보았다. !! 노점들은 나에게 미니 심장 마비를 주었다 .. !! 같은 레지스터를 사용하여 결과를 축적하는 문제는 무거운 실속으로 이어지고 @ auselen의 대답을 읽습니다 [여기] (http://stackoverflow.com/questions/12932940/using-neon-multiply-accumulate-on-ios) – nguns

    +2

    좋은 동일한 레지스터를 사용하여 결과를 누적하는 것에 대해 알고 있어야합니다. 여러 레지스터를 인터리빙하면 문제를 해결할 수 있습니다. 주목할 또 다른 사항은 연속적으로 너무 많은 PLD를 사용하지 않는 것입니다. 그렇지 않으면 모든 읽기 요청을 채우기를 기다리고 있기 때문에 메모리 읽기를 멈추게됩니다. 메모리 속도는 하드웨어에 따라 크게 달라집니다. 최근에 저는 DDR3 메모리가 장착 된 Qualcomm MSM8074와 함께 작업 해 왔으며 메모리 처리 속도는 상당히 인상적이었습니다. 명령 스톨과 메모리 스톨은 해당 시스템에서 거의 동일합니다. – BitBank

    관련 문제