Цитата(NickS @ Oct 18 2005, 04:49)
Судя по всему вы не писали достаточно большие проекты на ASM.
У меня, конечно, довольно редко воникает проект продублированный на С и ASM. Однако, например для кодека G.723.1 переписывание только базовых функций на ASM привело к уменьшению времени обработки одного фрейма с 200мс до 25, что соответствует примерно 10 кратному ускорению времени выполнения. Для обработчика обмена по USB выигрышь по скорости обработки выросло в 4 раза.
Я не работаю в этих областях, и к сожалению не могу прокомментировать данные цифры. Но 200 мс и 25 вообще выглядит весьма странно.
Цитата
Умножение на окно и авсолютное значение - функции достаточно простые.
Да, простые, поэтому и писание их заняло не более получаса, с учетом настройки опций этого тестового проекта и приведения ваших исходников к синтаксису IAR. Итак, IAR 4.30:
Функция window, ваш вариант:
Код
; GLOBAL window
PUBLIC window
window
stmfd r13!,{r2-r3,r14}
ldr r14,=WINTABLE
mov r1,r1,lsl #1
win_l0
ldrsh r2,[r14],#2;WIN[i]
ldrsh r3,[r0] ;Buf[i]
mul r3,r2,r3
mov r3,r3,asr #15
strh r3,[r0],#2;Buf[i]
subs r1,r1,#1
bgt win_l0
ldmfd r13!,{r2-r3,pc}
Функция window, мой вариант:
Код
static const signed short Rfft_c_wintbl[2048] = {...}
void window_c (signed short *Buf, int Len)
{
const signed short *win = Rfft_c_wintbl;
do
{
*Buf = (*Buf * *win) /65536;
Buf++;
win++;
} while (--Len);
}
143 void window_c (signed short *Buf, int Len)
144 {
145 const signed short *win = Rfft_c_wintbl;
\ window_c:
\ 00000000 24209FE5 LDR R2,??window_c_0 ;; ??Rfft_c_wintbl
146
147 do
148 {
149 *Buf = (*Buf * *win) /65536;
\ ??window_c_1:
\ 00000004 F030D0E1 LDRSH R3,[R0, #+0]
\ 00000008 ........ LDRSH R12,[R2], #+0x2
\ 0000000C 9C0303E0 MUL R3,R12,R3
\ 00000010 C3C7A0E1 MOV R12,R3, ASR #+0xF
\ 00000014 2C3883E0 ADD R3,R3,R12, LSR #+0x10
\ 00000018 4338A0E1 MOV R3,R3, ASR #+0x10
\ 0000001C ........ STRH R3,[R0], #+0x2
150 Buf++;
151 win++;
152 } while (--Len);
\ 00000020 011051E2 SUBS R1,R1,#+0x1
\ 00000024 F6FFFF1A BNE ??window_c_1
153 }
\ 00000028 0EF0A0E1 MOV PC,LR ;; return
\ ??window_c_0:
\ 0000002C ........ DC32 ??Rfft_c_wintbl
Все тело цикла практически одинаково, за исключением деления на 65536,
что в вашем варианте выглядит просто как арифметический сдвиг
Код
mov r3,r3,asr #15
а в варианте компилятора, как
Код
\ 00000010 C3C7A0E1 MOV R12,R3, ASR #+0xF
\ 00000014 2C3883E0 ADD R3,R3,R12, LSR #+0x10
\ 00000018 4338A0E1 MOV R3,R3, ASR #+0x10
Что по сути правильно, поскольку в вашем варианте при делении отрицательного числа никогда не будет получен 0, максимум -1. В общем, округление результата будет несколько не туда и в разные стороны для положительных и отрицательных чисел. Возможно, в вашем приложении это качественно и не сказывается на окончательный результат, но тем не менее, в ТЗ было прописано деление.
Далее, функция abs, ваша
Код
abs_l0
ldrsh r2,[r0];Buf[i]
mul r3,r2,r2
ldrsh r2,[r0,#2];Buf[i]
mla r3,r2,r2,r3
mov r3,r3,asr #14
str r3,[r0],#4;Buf[i]
subs r1,r1,#1
bgt abs_l0
моя
Код
void absr_c (short *Buf, int Len)
{
unsigned int *p_out = (unsigned int *)Buf;
do
{
int temp = *Buf * *Buf;
Buf++;
temp += *Buf * *Buf;
Buf++;
*p_out++ = temp;
} while (--Len);
}
155 void absr_c (short *Buf, int Len)
156 {
157 unsigned int *p_out = (unsigned int *)Buf;
\ absr_c:
\ 00000000 0020A0E1 MOV R2,R0
158
159 do
160 {
161 int temp = *Buf * *Buf;
\ ??absr_c_0:
\ 00000004 F030D0E1 LDRSH R3,[R0, #+0]
\ 00000008 93030CE0 MUL R12,R3,R3
162 Buf++;
163 temp += *Buf * *Buf;
\ 0000000C F230F0E1 LDRSH R3,[R0, #+0x2]!
\ 00000010 93C32CE0 MLA R12,R3,R3,R12
164 Buf++;
\ 00000014 020080E2 ADD R0,R0,#+0x2
165 *p_out++ = temp;
\ 00000018 ........ STR R12,[R2], #+0x4
166 } while (--Len);
\ 0000001C 011051E2 SUBS R1,R1,#+0x1
\ 00000020 F7FFFF1A BNE ??absr_c_0
167 }
\ 00000024 0EF0A0E1 MOV PC,LR ;; return
То есть издержки Ц - дополнительная команда ADD R0,R0,#+0x2.
Кроме того, у вас там есть масштабирование результата mov r3,r3,asr #14
хотя по ТЗ это описано не было. При добавлении масштабирования код для этой операции создается такой же, как и в верхнем примере.
Цитата
А real FFT предлагается в довольно большом количестве библиотек если лень писать самому.
Это уже не так быстро, а поскольку я это делаю в рабочее время, то я возьму таймаут для написание этих функци и попробую протестировать на реальном железе. Впрочем, скоро не обещаю.