2012-06-20 1 views
1

적어도 ARMv5까지의 ARM CPU는 워드 정렬되지 않은 메모리 주소에 대한 임의 액세스를 허용하지 않습니다. 문제의 길이는 여기에 설명되어 있습니다 : http://lecs.cs.ucla.edu/wiki/index.php/XScale_alignment - 하나의 해결책은 코드를 다시 작성하거나 처음부터이 정렬을 고려하는 것입니다. 그러나 그것은 어떻게 말하지 않았습니다. 바이트 스트림에서 2 바이트 또는 4 바이트 정수가 있고 스트림에 단어가 정렬되어 있지 않습니다. 성능을 많이 저하시키지 않으면 서이 데이터에 현명한 방법으로 어떻게 액세스합니까?ARM 프로세서에서 워드 정렬 데이터에 무작위로 액세스하는 방법은 무엇입니까?

filling buffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 
accessing with short: 0100 0201 0302 0403 0504 0605 0706 0807 0908 0A09 0B0A 0C0B 0D0C 0E0D 0F0E 
accessing with long: 03020100 04030201 05040302 06050403 07060504 08070605 09080706 0A090807 0B0A0908 0C0B0A09 0D0C0B0A 0E0D0C0B 0F0E0D0C 

ATMEL AT91SAM9G20 ARMv5 코어에 내가 (주 얻을 :

내가 문제를 설명하는 코드가 있습니다 출력 이것을 86 CPU에

#include <stdio.h> 
#include <stdlib.h> 

#define BUF_LEN 17 

int main(int argc, char *argv[]) { 
    unsigned char buf[BUF_LEN]; 
    int    i; 
    unsigned short *p_short; 
    unsigned long *p_long; 

    /* fill array */ 
    (void) printf("filling buffer:"); 
    for (i = 0; i < BUF_LEN; i++) { 
     /* buf[i] = 1 << (i % 8); */ 
     buf[i] = i; 
     (void) printf(" %02hhX", buf[i]); 
    } 
    (void) printf("\n"); 

    /* testing with short */ 
    (void) printf("accessing with short:"); 
    for (i = 0; i < BUF_LEN - sizeof(unsigned short); i++) { 
     p_short = (unsigned short *) &buf[i]; 
     (void) printf(" %04hX", *p_short); 
    } 
    (void) printf("\n"); 

    /* testing with long */ 
    (void) printf("accessing with long:"); 
    for (i = 0; i < BUF_LEN - sizeof(unsigned long); i++) { 
     p_long = (unsigned long *) &buf[i]; 
     (void) printf(" %08lX", *p_long); 
    } 
    (void) printf("\n"); 

    return EXIT_SUCCESS; 
} 

인이있다 이 CPU의 예상되는 동작!) :

filling buffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 
accessing with short: 0100 0100 0302 0302 0504 0504 0706 0706 0908 0908 0B0A 0B0A 0D0C 0D0C 0F0E 
accessing with long: 03020100 00030201 01000302 02010003 07060504 04070605 05040706 06050407 0B0A0908 080B0A09 09080B0A 0A09080B 0F0E0D0C 

그래서 주어진 바이트 스트림에 액세스해야합니다. 정렬되지 않은 주소에서 : ARM에서 어떻게 효율적으로 처리 할 수 ​​있습니까?

+1

정렬을하면 성능이 떨어지며 팔과 밉 등으로 제한되지 않습니다. x86 정렬 액세스에서도 성능이 크게 향상되고 ARM뿐 아니라 모든 곳에서 수행해야하는 작업입니다. –

답변

2

정렬 된 변수와 정렬되지 않은 바이트 스트림 사이를 변환하는 사용자 고유의 패킹/언 패킹 함수를 작성합니다. 예 :

void unpack_uint32(uint8_t* unaligned_stream, uint32_t* aligned_var) 
{ 
    // copy byte-by-byte from stream to var, you can fill in the details 
} 
1

이 예에서는 모든 플랫폼에서 문제를 보여줍니다. 물론 간단한 수정 :

unsigned char *buf; 
int    i; 
unsigned short *p_short; 
unsigned long p_long[BUF_LEN>>2]; 

당신이 더 정렬을 사용하여 데이터를 (더 바이트 시간이 더 나은 성능을 동일 수에) 구성 할 수없는 경우는 그 다음 명백한을하고 32 비트 등 모든 것을 해결하고 거기에서 부분을 잘라 옵티마이 저는 단어 내의 단락과 바이트 (구조체의 바이트와 단락을 포함하여 메모리에서 선택되는 구조 나 바이트를 포함하여)에서 많은 부분을 처리하므로 추가 지침이있을 때보 다 비용이 많이들 수 있습니다 주변에 모든 것을 단어로 전달했습니다. 시스템 엔지니어링을해야합니다.)

정렬되지 않은 단어를 추출하는 예입니다.

a = (lptr[offset]<<16)|(lptr[offset+1]>>16); 

현재까지 ARMV4의 모든 ARM 코어는 기본적으로 대부분의 예외가 켜져 있지만 당신이 그것을 해제 할 수 있습니다, 정렬되지 않은 액세스를 허용 (물론 당신의 엔디안을 관리 할 수 ​​있습니다). 이제는 오래된 단어가 단어 내에서 회전하지만 다른 단어가 잘못 입력되지 않으면 다른 문자를 가져올 수 있습니다.

시스템 엔지니어링을 수행하고 성능 분석을 수행하고 모든 것을 단어로 빠르게 또는 느리게 이동 시킬지 결정하십시오. 데이터의 실제 이동에는 약간의 오버 헤드가 있지만 모든 것이 정렬되면 양측의 코드가 훨씬 빠르게 실행됩니다. 데이터 생성 및 수신에 대해 2 배에서 4 배까지 향상되도록 X 배 느린 데이터 이동을 몇 번 시도해도됩니까?

0

기능이 항상 32 비트 액세스 정렬 사용

uint32_t fetch_unaligned_uint32 (uint8_t *unaligned_stream) 
{ 
    switch (((uint32_t)unaligned_stream) & 3u) 
    { 
     case 3u: 
      return ((*(uint32_t *)unaligned_stream[-3]) << 24) 
       | ((*(uint32_t *)unaligned_stream[ 1]) & 0xffffffu); 
     case 2u: 
      return ((*(uint32_t *)unaligned_stream[-2]) << 16) 
       | ((*(uint32_t *)unaligned_stream[ 2]) & 0x00ffffu); 
     case 1u: 
      return ((*(uint32_t *)unaligned_stream[-1]) << 8) 
       | ((*(uint32_t *)unaligned_stream[ 3]) & 0x0000ffu); 
     case 0u: 
     default: 
      return *(uint32_t *)unaligned_stream; 
    } 
} 

그것은 판독 별도로 4 바이트 시프트보다 더 빠를 수있다.

관련 문제