2010-12-02 2 views
2

코드에서 가능하면 서명되지 않은 정수를 사용하는 습관이 있습니다. 서명 된 유형으로는 처리 할 수없는 부호없는 유형에 대해 2의 제곱으로 나누기가 가능하기 때문입니다. 속도는이 프로젝트에 중요합니다. 프로세서는 최대 40 MIPS에서 작동합니다.임베디드 플랫폼에서 (implicity signed) int 대신 unsigned int를 사용하는 것이 더 효율적입니까?

내 프로세서에는 18 사이클 나눗셈이 있지만 단일 사이클 배럴 시프터보다 오래 걸립니다. 따라서 속도를 높이기 위해 여기에 부호없는 정수를 사용하거나 다른 단점을 가져올 가치가 있습니까? 마이크로 칩의 dsPIC33F 시리즈 회원 인 dsPIC33FJ128GP802를 사용하고 있습니다. signed int와 unsigned int 모두에 대해 단일 사이클 곱하기를가집니다. 그것은 또한 부호와 제로 확장 명령을 가지고있다.

예를 들어 부호있는 정수와 부호없는 정수를 혼합 할 때이 코드가 생성됩니다.

026E4 97E80F  mov.b [w15-24],w0 
026E6 FB0000  se w0,w0 
026E8 97E11F  mov.b [w15-31],w2 
026EA FB8102  ze w2,w2 
026EC B98002  mul.ss w0,w2,w0 
026EE 400600  add.w w0,w0,w12 
026F0 FB8003  ze w3,w0 
026F2 100770  subr.w w0,#16,w14 

내가 C (의 dsPIC을위한 GCC.)

+1

왜'typedef'를 사용하여 두 가지 방법으로 시도해보십시오 (그리고 벤치 마크)? –

+1

출력 내용이 "서명되거나 서명되지 않은 상태로 사용되지만 함께 섞어서는 안됩니다"라고 생각합니다. –

+1

@Karl Knechtel 대부분의 코드가 부호가있는 int로 중단됩니다. 또한 전용 스레드, 제한된 타이머 자원 및 연속 인터럽트가없는 경우 벤치마킹하기가 상당히 어렵습니다. –

답변

2

을 사용하고 우리 모두가이 질문에 대답하기 위해 프로세서의 특수성에 대해 더 많이 알 필요가 있다고 생각합니다. 부호있는 정수에서 2의 제곱으로 나눗셈을 할 수없는 이유는 무엇입니까? 내가 아는 한이 작업은 두 작업 모두 동일합니다. 나는.

10/2 = 00001010은 00000101

-10/2 = 11110110은 11111011

로 이동에 어쩌면 당신은 부호 분할을하고 몇 가지 간단한 코드와 서명 격차를 작성하고 컴파일 된 출력을 비교해야 간다.

또한 벤치마킹을하는 것이 좋습니다. 정확할 필요는 없습니다. 수천 개의 숫자 배열을 가지고 타이머를 시작하고 수백만 배와 시간이 걸리는 시간을 나누기 시작하십시오. 프로세서가 빠르면 아마 수십억 번 할 수 있습니다. 예 :

int s_numbers[] = { etc. etc. }; 
int s_array_size = sizeof(s_numbers); 
unsigned int u_numbers[] = { etc. etc.}; 
unsigned int u_array_size = sizeof(u_numbers); 
int i; 
int s_result; 
unsigned int u_result; 

/* Start timer. */ 

for(i = 0; i < 100000000; i++) 
{ 
    i_result = s_numbers[i % s_array_size]/s_numbers[(i + 1) % s_array_size]; 
} 

/* Stop timer and print difference. */ 

/* Repeat for unsigned integers. */ 

서둘러 서면 원칙을 보여 주므로 오류를 양해 해주십시오.

정확한 벤치마킹을 제공하지는 않지만 더 빨리 수행 할 수있는 일반적인 아이디어를 제공해야합니다.

+0

제수가 2의 거듭 제곱 인 경우 부호가있는 정수를 나눌 수 있습니다. 부호없는 정수보다 더 오래 걸립니다. –

+0

@AlastairG : '246/2 = 11110110' _goes_ _to_'01111011'. 특정 아키텍처가 더 나은 산술적 인 구절을 논리적으로 오른쪽으로 이동하거나 그 반대의 경우에는 문제가 될 수 있습니다. – nategoose

+0

@AlastairG : 오른쪽 시프트는 C99에서'-9/2'와 같은 부문에 대해 올바른 결과를주지 않습니다. C99는 '0으로 반올림'을 지정하므로 해당 나누기의 결과는 '-4'이어야하지만 ' -5 '. – caf

0

프로세서에서 사용할 수있는 명령어 세트에 대해 많이 알지는 못하지만 간단히 살펴보면 산술 및 논리 교대에 사용할 수있는 명령어가 있다고 생각하므로 서명 된 값을 변경하면 부호없는 값을 시프 팅하는 것과 같고, 시프트를 사용하여 각각 2의 제곱으로 나누는 경우에도 비용이 동일해야합니다. (내 지식은 프로세서 제품군을 대상으로하는 C 컴파일러의 일부 내장 함수를 간략하게 살펴 본 것입니다.)

즉, 부호없는 것으로 해석 될 값으로 작업하는 경우 서명되지 않은 것으로 선언 할 수 있습니다. 지난 몇 년 동안 나는 stdint.h의 형식을 점점 더 많이 사용 해왔다. 보통은 부호없는 버전을 사용했다. 왜냐하면 내 값이 본질적으로 부호가 없거나 그냥 비트 배열로 사용하기 때문이다.

0

조립품을 생성하고 횟수를 계산하십시오.

0

부호 확장에 대해 걱정할 필요없이 필요에 따라 간단히 오른쪽 시프트를 수행 할 수 있기 때문에 부호없는 2의 제곱수 나누기가 빠릅니다.

단점 : 산술 오버플로 감지, 서명되지 않은 유형의 오버플로, 부호없는 유형 사용 중 인식하지 못했기 때문에 오버플로아무것도 막지 않으며, 조심해야 할 다른 것들.

관련 문제