2013-08-01 5 views
0

NEON을 사용하는 ARM 프로세서 용 코드 최적화 작업을하고 있습니다. 그러나 문제가 있습니다 : 내 알고리즘에 다음 부동 소수점 계산이 포함되어 있습니다.ARM NEON 어셈블리 및 부동 소수점 올림 반올림

round(x*b - y*a) 

여기서 결과는 양수와 음수 일 수 있습니다.

사실 저는 2 개의 VMUL과 1 개의 VSUB를 사용하여 병렬 계산을합니다 (Q 레지스터와 32 비트 부동 소수점을 사용하는 연산 당 4 개의 값).

이 문제를 해결할 수있는 방법이 있습니까? 결과가 모두 같은 기호 인 경우 간단히 더하거나 뺄 수 있습니다. 0.5

답변

1

먼저 NEON은 특히 부동 소수점 곱셈 이후 긴 대기 시간이 있습니다. 당신은 vfp 프로그래밍과 비교하여 두 vmuls와 하나의 vsub로 많은 이득을 얻지 못할 것입니다.

vmul.f32 result, x, b 
vmls.f32 result, y, a 

그 곱셈 - 덧셈/빼기 지침을 맞대고있는 대기 시간없이 이전의 곱셈 명령과 함께 발행 :

따라서, 귀하의 코드처럼 보일 것입니다. (이 경우 저장된 9 사이클)

그러나 불행히도, 나는 실제 질문을 이해하지 못합니다. 왜 누군가는 부동 소수점 값을 반올림하기를 원할 것입니까? 분명히 정수 부분을 반올림하려는 의도가 있습니다.이 작업을 수행 할 수있는 몇 가지 방법이 있습니다. 질문이 항상 너무 애매하기 때문에 더 이상 말할 수 없습니다.

나는 꽤 오랫동안이 포럼에서 귀하의 질문에 따라 왔으며 나는 당신이 매우 근본적인 것이 부족하다는 느낌을 없앨 수 없습니다.

먼저 ARM의 어셈블리 참조 안내서 pdf를 읽어 보시기 바랍니다.

+0

안녕하세요, 네 정수 부분을 반올림해야합니다. 의견을 보내 주셔서 감사합니다. 가능한 빨리 참조 가이드를 읽어 드리겠습니다. 블로그를 팔로우하고 있습니다. 매우 흥미 롭습니다. –

+0

그러면 float 형식으로 반올림하지 않아도됩니다. vcvt.s32.f32를 사용하여 float를 int로 변환하고 1 분수 비트로 변환하면 vrshr.s32로 반올림을 수행 할 수 있습니다. 그게 내가 "당신의 문제에 더 구체적이라는 의미입니다." –

+0

VCVT 명령에서 #fbits 옵션 값을 놓쳤습니다. 귀하의 솔루션을 테스트했습니다 : 양수 값은 괜찮지 만 음수 값은 반올림되지 않습니다. -0.9는 0으로 반올림되고 -1로 반올림되지 않습니다. –

1

저는 어셈블리에 대한 지식이 없지만 C에서 NEON 내장 함수를 사용합니다 (설명서를 탐색하는 데 도움이되는 어셈블리 관련 동등 함을 언급합니다. 직접 사용할 수는 없지만) round 함수의 알고리즘 수 :

// Prepare 3 vectors filled with all 0.5, all -0.5, and all 0 
// Corresponding assembly instruction is VDUP 
float32x4_t plus = vdupq_n_f32(0.5); 
float32x4_t minus = vdupq_n_f32(-0.5); 
float32x4_t zero = vdupq_n_f32(0); 

// Assuming the result of x*a-y*b is stored in the following vector: 
float32x4_t xa_yb; 

// Compare vector with 0 
// Corresponding assembly instruction is VCGT 
uint32x4_t more_than_zero = vcgtq_f32(xa_yb, zero); 
// Resulting vector will be set to all 1-bits for values where the comparison 
// is true, all 0-bits otherwise. 

// Use bit select to choose if you have to add or substract 0.5 
// Corresponding assembly instruction is VBSL, its syntax is quite alike 
// `more_than_zero ? plus : minus`. 
float32x4_t to_add = vbslq_f32(more_than_zero, plus, minus); 

// Add this vector to the vector to round 
// Corresponding assembly instruction is VADD, 
// but I guess you knew this one :D 
float32x4_t rounded = vaddq_f32(xa_yb, to_add); 

// Then cast to integers! 

을 내가 (어쨌든, 내가 아니에요) 당신이 어셈블리에이를 변환 할 수 있습니다이 정말 표준 코드보다 더 효율적이다 만약 내가 아무 생각이

주를 추측, 비 - SIMD 코드!

관련 문제