2009-03-24 1 views
1

Вот моя попытка. Любые советы о лучшем решении ?:Самый быстрый способ проверки переполнения?

// for loop to convert 32 to 16 bits 
uint32_t i; 
int32_t * samps32 = (int32_t *)&(inIQbuffer[0]); 
int16_t * samps16 = (int16_t *)&(outIQbuffer[0]); 
for(i = 0; i < (num_samples * 2/* because each sample is two int32 s*/); i++) { 
    overflowCount += (abs(samps32[i]) & 0xFFFF8000) ? 1 : 0; 
    samps16[i] = (int16_t)samps32[i]; 
} 

// Only report error every 4096 accumulated overflows 
if((overflowCount & 0x1FFF) > 4096) { 
    printf("ERROR: Overflow has occured while scaling from 32 " 
      "bit to 16 bit samples %d times", 
      overflowCount); 
} 

Вот та часть, которая на самом деле проверяет переполнение:

overflowCount += (abs(samps32[i]) & 0xFFFF8000) ? 1 : 0; 
+0

Мы преобразуем int32_t в int16_t. –

+0

Просто хотел упомянуть: «В соответствии с вашим редактированием (http: // stackoverflow.com/revision/677427/list), вы поехали почти на весь мой пост. Спасибо за то, что вы не указали свое изменение в своем вопросе ». –

+0

Вниз из-за вашего сбивающего с толку и бесполезного редактирования. –

ответ

1

Кажется, что вы проверяете переполнение 16-битного сложения. Вы можете избежать ветви в коде ассемблера просто имея

overflowCount += (samps32[i] & 0x8000) >> 15; 

Это создает три операции ALU, но ни одна ветвь в коде. Он может быть или не быть быстрее, чем версия ветвления.

3

Я лично предпочитаю использовать класс SafeInt, чтобы сделать мою проверку переполнения. Это уменьшает необходимость в утомительной проверке ошибок и превращает его в легко обрабатываемое, но с трудом игнорируемое исключение.

http://blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx

2

То, что вы уже делаете, ближе всего к fastests возможно для одного броска. Однако вы можете опустить некоторый код

overflowCount + = (абс (samps32 [I]) & 0xFFFF8000)? 1: 0;

может быть изменен в:

если (samps32 [I] & 0xFFFF8000) overflowCount ++;

или даже проще

если (samps32 [I] >> 15) overflowCount ++;

оба они будут одинаково быстры, и оба будут быстрее, чем ваши.

Если вы действительно перепробованы в счете переполнения, вы можете рассмотреть возможность обработки массива целых чисел с помощью операций SIMD.

+0

Они не обязательно бывают быстрее. Тройная операция OP довольно тривиальна и может быть оптимизирован для условного перемещения компилятором, так как это может быть и ваша альтернатива. Даже если нет доступных cmove, ваш код все равно может ухудшиться из-за условной ветви ... –

+0

... тогда как –

+0

Нет необходимости в условном ветвлении, компилятор может использовать инструкции 'setz' и т. д. –

0

Бит опс был бы моим выбором. единственный способ, который я могу себе представить на данный момент, - использовать встроенную сборку, где вы загружаете исходный операнд, делаете копию на чипе, обрезаете и побитовое сравнение (это псевдо псевдодекс).

В вашем коде есть проблема: он нарушает правила псевдонимов. Вместо этого вы можете использовать что-то вроде этого:

union conv_t { 
    int32_t i32; 
    int16_t i16; 
}; 

Тогда вы могли бы убедиться, что IQBuffer имеет такой тип. Наконец, вы можете запустить:

for(i = 0; i < (num_samples * 2); i++) { 
    <test goes here> 
    samps [i].i16 = static_cast<int16_t>(samps [i].i32); 
} 

редактировать: согласно вашим редактировать (https://stackoverflow.com/revisions/677427/list) вы ехали почти весь мой пост недействителен. Спасибо за то, что вы не указали свое изменение в своем вопросе.

 Смежные вопросы

  • Нет связанных вопросов^_^