Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Asm: Общие вопросы > КИХ-фильтр (MMX)


Автор: andreyasa 24.12.2007, 00:31
Здравствуйте помогите пожалуйста ускорить программу на Ассемблере. Преподаватель говорит что ее можно ускорить в 4 или 8 раз. Говорит это легко и быстро !!!  Преподаватель как только увидел вот эту строчку кода 
;Записываем результат
MOV [edi], eax
сразу сказал что остальное даже можно не смотреть. Он говорит что нам надо на вход вектор и на выходе получать вектор. Мы запутались. Ниже для понимая даем краткую информацию.
ОС Windows XP

1.    Постановка задачи

Разработать и реализовать программу, осуществляющую фильтрацию большого массива данных методом простого скользящего среднего с использованием возможностей оптимизации, предоставляемых процессорами Intel Pentium MMX. 


2.    Описание реализуемого КИХ-фильтра

Цифровая фильтрация является одним из наиболее мощных инструментальных средств ЦОС. Цифровые фильтры широко используются в телекоммуникациях, в приложениях адаптивной фильтрации, таких как подавление эха в модемах, подавление шума и распознавание  речи.  Существует два основных типа цифровых фильтров: фильтры с конечной импульсной характеристикой (КИХ) и фильтры с бесконечной импульсной характеристикой (БИХ). Как следует из терминологии, эта классификация относится к импульсным характеристикам фильтров. 
Примером простого КИХ-фильтра является фильтр скользящего среднего (простое прямоугольное окно). Приведем формулу 4-точечного фильтра.

                                                                


На основе приведенного примера выведем алгоритм работы фильтра:
 - первым шагом происходит запоминание первых семи элементов A(0), A(1), A(2), A(3), A(4), A(5), A(6) в регистрах
- эти величины суммируются и затем полученная сумма делятся   
  на 7.
- начальные значения выходов y(0), y(1), y(2) некорректны.
- конечные значения выходов y(N-3), y(N-2), y(N-1) 
  некорректны.

Затем алгоритм повторяется для всего набора данных. Следует отметить, что качество фильтрации увеличивается при увеличении числа блоков (количества точек, по которым берется среднее)

3.    Описание программы

В программе представлены два варианта реализации КИХ-фильтра: реализация на С++ и ассемблере с использованием MMX команд. Для проведения анализа двух реализаций имеется счетчик времени выполнения фильтрации. Что позволяет судить о эффективности той или иной реализации. 
Данные для фильтрации также генерируются в программе. Перед выполнением алгоритма производится нормировка сгенерированных значений.
4. Исходный код программы

1.Реализация на С++ 
 
 Представляет собой последовательность вызовов операторов и библиотек языка высокого уровня, что не дает существенно выигрыша по времени выполнения фильтрации: 

void CKurs_MMXDoc::KIX_C()
{ 
    for(int t=3;t<1020;t++)
    {
        m_dMasSigKIX_C[t] = m_iMasTemp[t-3];
        m_dMasSigKIX_C[t] += m_iMasTemp[t-2];
        m_dMasSigKIX_C[t] += m_iMasTemp[t-1];
        m_dMasSigKIX_C[t] += m_iMasTemp[t];
        m_dMasSigKIX_C[t] += m_iMasTemp[t+1];
        m_dMasSigKIX_C[t] += m_iMasTemp[t+2];
        m_dMasSigKIX_C[t] += m_iMasTemp[t+3];
        m_dMasSigKIX_C[t] = m_dMasSigKIX_C[t]/7;
    }
}
Время выполнения фильтрации: 0,076 mc

2.Реализация на ассемблере 

В данной реализации используются особый набор команд (MMX), которые позволяют организовать параллельную обработку нескольких блоков данных, что позволяет существенно сократить время выполнения процесса фильтрации. А именно, использование специальных команд векторной обработки данных (MMX), позволяет получить за одну итерацию две отфильтрованных точки.

void CKurs_MMXDoc::KIX_MMX(int *p1, int *p2)
{
    __asm
    {
        MOV esi, p1
        MOV edi, p2
        MOV ecx, 1017
again:
        PXOR mm2, mm2

        ;Считываем 4 элемента в ММХ регистры 
        MOVQ mm0, [esi]
        MOVQ mm1, [esi+8]

        ;Вычисляем сумму элементов
        PADDD mm1, mm0

        ;Считываем 3 элемента в ММХ регистры 
        MOVQ mm0, [esi+16]
        MOVD mm2, [esi+24]

        ;Вычисляем сумму элементов
        PADDD mm0, mm2
        PADDD mm1, mm0

        MOVQ mm0, mm1
        PSRLQ mm1, 32
        PADDD mm1, mm0
        ;Сумма элементов в регистр EAX
        MOVD eax, mm1

        ;Делим сумму на 7
        MOV ebx, 7
        CDQ
        IDIV ebx

        ;Записываем результат
        MOV [edi], eax

        ;Переход к следующему элементу
        ADD esi, 4
        ADD edi, 4

        LOOP again        

        EMMS
    }
}
Время выполнения фильтрации: 0,041 mc


Автор: cardinal 24.12.2007, 03:34
1. не уверен, но помоему JMP быстрее выполняется, чем LOOP.
2. возьми 8 значений (вместо семи) и дели на 8 сдвигом вправо (на три).
3. пользуйся тегом "код"!

Автор: SABROG 27.12.2007, 13:17
Все операции с памятью - медленные, поэтому лучше всего использовать незадействованные регистры. Скажем распихивать несколько результатов по регистрам, а потом разом сливать. С лупом и джампом тоже ситуация неоднозначная, лучше всего воспользоваться "разворачиванием цикла", если мне память не изменяет то с каждым джампом/лупом сбрасывается кэш, а на это уходит время. Разворачивание цикла позволит запихнуть больше кода в кэш и увеличить скорость выполнения программы. На размеры программ сейчас уже никто не смотрит.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)