Консультация № 66122
08.12.2006, 16:35
0.00 руб.
0 8 2
Уважаемые экперты!!

Мне потребоваль реализовать скоростное копирование значений (тип WORD) из одного массива в другой, кроме тех значений что совпадают с exclude. Вот так выглядит реализация на си. Но мне нужно ещё больше скорости, подскажите реализацию данного алгоритма на ассемблере.

ЗЫ Требуется интеграция в си.


Приложение:
void CopyArrayExclude(WORD * to, WORD * from, int size, WORD exclude){WORD * end = from + size;for (; from < end; ++from, ++to){if (*from != exclude)*to = *from;++to;++from;if (from < end){if (*from != exclude)*to = * from;}}}

Обсуждение

Неизвестный
08.12.2006, 17:08
общий
это ответ
Здравствуйте, Golden Spider!

Смело можете писать:
void CopyArrayExclude(WORD * to, WORD * from, int size, WORD exclude){
int i,j=0;
for(i=0;i<size;i++){if(to!=exclude...
}
}
На самом деле Си такие конструкции очень сильно оптимизирует в зависимости от контекста в котором используется данная функция - выйгрыша может не получится вообще...

Если очень хочется на ассемблере, то это будет выглядеть примерно так (для массивов средних размеров):
void CopyArrayExclude(WORD * to, WORD * from, int size, WORD exclude){
asm
{
mov bx,exclude
mov di,to;//для 32-х бит: mov edi,to
mov si,from;//для 32-х бит: mov esi,from
xor ecx,ecx
mov cx,size
cld
}
mv:
asm
{
lodsw
or ax,bx
jz mve
stosw
}
mve:
asm loop mv;
}
Неизвестный
08.12.2006, 19:55
общий
это ответ
Здравствуйте, Golden Spider!
из твоего кода становится понятно, что если исходное значение равно исключаемому, то значение в целевой массив не переписывается, а просто пропускается?
вообще, современные компиляторы С++ действительно хорошо оптимизируют код, так что прежде всего нужно посмотреть, что сгенерит тут компилятор.
на мой взгляд, место для улучшения - это условные переходы. процессор сильно тормозит, если не угадывает условный переход, поэтому условные переходы лучше исключать. предлагаю код в приложении. он не изменяет содержимое ячеек памяти целевого массива, если в исходном на соотв. месте стоит код исключения. если туда можно записывать, например, 0 на это место, код упрощается.
в коде использован метод cmp + sbb для избежания условного перехода.
также можно попробовать реализовать данную задачу с помощью ММХ (оно как раз заточено под 16-ти разрядные числа).

Приложение:
mov bx, [size] mov si, [src] dec bx mov di, [dst] mov cx, [exclude] shl bx, 1m1: mov ax, [si + bx] ; if current word must be excluded: sub ax, cx ; ax = 0 cmp ax, 1 ; C flag is set sbb dx, dx ; dx = 0xFFFF mov bp, dx ; bp = 0xFFFF xor dx, 0xFFFF ; dx = 0 and bp, [di + bx] and dx, [si + bx] or dx, bp sub bx, 2 mov [di + bx], dx jnc m1
Неизвестный
09.12.2006, 00:55
общий
может это и не в тему, но если вы пишете не под обычный компьютер, а под какой-нибудь КПК или смартфон, то может быть там другие приколы с ассемблером, т.е. могут отсутствовать какие-нибудь команды. Так что если вы действительно пишете не для обычного компьютера, то посмотрите справку по ассемблеру используемого процессора.
Неизвестный
09.12.2006, 11:52
общий
действительно пишу для КПК, но асм проверял почти все команды совпадают...
Неизвестный
09.12.2006, 13:20
общий
так надо было в вопросе указать... там оптимизация может быть совсем другой (например, стоимость ошибки предугадывания условного перехода не так критична; нет параллельных конвееров и т.п.)
Неизвестный
09.12.2006, 18:48
общий
я проверял скорость выполнения с точностью до миллисекунды скорость действительно возрасла в вашем случае... в 3.7 раза :)
Неизвестный
10.12.2006, 02:03
общий
на чем проверял и с чем сравнивал?
Неизвестный
10.12.2006, 12:35
общий
со своей первой функцией. Скорость её выполнения (time1-time2) там получалось несколько десятков миллисекунд, к сожелению ваш вариант ещё не проверил только ADSota, так у него как я уже говорил в несколько раз меньше (время выполниния), по крайней мере для небольших массивов. ЗЫ единственное отличие моего (smartphone) асма от ПК-ного , описывается не asm {}; , а так __asm{};:)
Форма ответа