Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 14 
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Вот назрел вопрос о создании процедуры сравнения двух блоков памяти и нахождение кол-ва не совпадений.
Задача такая, блоки памяти одинакового размера и всегда кратны 4. Сравнение идет не по байтам , а по DWORD.
Стандартная CompareMem в Delphi пашет очень быстро, сравнение двух блоков по 30 мегов каждый проходит за 40-42 тика (GetTickCount до и после), но эта процедура выходит при нахождении первого не совпадения.
Я набросал простой вариант
Код:
function MCompareMem(p1, p2: pointer; size: Integer;var mismatch:dword): boolean;
var i:longint;
    dw1,dw2:^DWORD;
    ms:dword;
begin
     dw1:=p1;
     dw2:=p2;
     mismatch:=0;
     ms:=size div 4;
     for i:=1 to ms do
     begin
          if dw1^<>dw2^ then
          begin
               inc(mismatch);
          end;
          inc(dw1);inc(dw2);
     end;
     result:=mismatch=0;
end;

по скорости также как и CompareMem , но вот думаю может можно как то еще ускорить? У кого есть идеи?



Партнер
 

Advanced member
Статус: Не в сети
Регистрация: 10.04.2003
Откуда: Москва
Ray Adams, зачем тебе такая суперскорость?
и ... может все-же сделать asm вставку? ;)


 

Member
Статус: Не в сети
Регистрация: 30.01.2003
Откуда: Москва
Код:
for ms := size div 4 - 1 downto 0 do ...
Будет быстрее на пару тиков процессора :)


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Asteroid Как раз нет, я специально смотрел что получается в АСМе, так вот
Код:
for ms := size div 4 - 1 downto 0 do ...

ты уверен что это меньше в асме? Я нет

serj_
Да вот понадобилось :), насчет асма, так этот код Delphi сам прекрасно перевел в асм , даже лучше чем я сам бы это сделал.
Просто подумываю над чем то иным, скажем с применение SSE ! :)


 

Advanced member
Статус: Не в сети
Регистрация: 10.04.2003
Откуда: Москва
Ray Adams писал(а):
скажем с применение SSE !
ага! давай, давай ... и получишь дикий провал для AMD. :)
Ладно, не хочешь сознаваться - твои проблемы.
Если сравниваются большие блоки, очень помогает prefetchnta. Для сравнения надо их выдавать два раза.
Кроме того, обязательно надо align 16 по первой инструкции цикла. И ... цикл с одной проверкой внутри себя - это уже порядка х2 меньше скорость.
Операции надо-бы делать с блоком.
(ты все еще хочешь обойтись без asm? :) )


 

Member
Статус: Не в сети
Регистрация: 23.09.2003
Откуда: South Ural
Ray Adams
по алгоритму: сравнение есть вычитание и если нужно знать количество всех несовпадений вычитать нужно все :)
оптимизировать тут практически нечего
по реализации: лучше всего конечно асмовская вставка - никакой компилятор не сможет понять что все что тебе нужно есть подобие repe cmps :) но рассматривая код сгенерированный делфи много чего есть улучшить не прибегая к асму и оптимизации под конкретные процессоры, выравнивания, парабельность команд, sse и т.п.
1. избегаем локальных переменных - они храняться в стеке - что есть память и работа с ними медленнее чем с регистрами; полезно также знать что делфи при использовании стандартного вызова fastcall старается разместить параметры в регистрах:
учитывая все это и то что с p1 и p2 работаем в цикле присваивание dw1:=p1; dw2:=p2; явно невыгодно (переносим переменные в медленную память из быстрого процессора :) )
2. мелкая оптимизация по размеру + помещение переменной в регистр :)
вместо ms:=size div 4 лучше написать size:=size shr 2;
3. использование цикла while do вместо for to - избавляемся от лишней локальной (стековой) переменной i

в результате получается что-то типа этого - возможно даже заработает - я не проверял :)
Код:
type pDWord = ^longword;
begin
  mismatch := 0;
  size := size shr 2;
  while size >= 0 do
  begin
    if pDWord(p1)^ = pDWord(p2)^ then
    begin
      inc(integer(p1), 4);
      inc(integer(p2), 4);
      dec(size);
    end
    else
      inc(mismatch);
  end;
  result:=mismatch=0;
end;

_________________
http://stargaz0r.nm.ru
http://people.overclockers.ru/StarGaz0r/files


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
serj_ Да я согласен и на АСМ, галвное чтобы быстро было, а что SSE такой фиговый под AMD полчуается? :) Ну тогда можно и на MMX, хотя это всеже тривиальная задача и все решается простейшими способами.
Цитата:
Ладно, не хочешь сознаваться - твои проблемы.

Сознаваться в чем? :)

stargaz0r проверил таже скорость :) 62 тика. Видимо уже оптимизировать это только перевода на АСМ хотя не уверен в том что будет лучше.
Но надо попробовать.


 

Member
Статус: Не в сети
Регистрация: 23.09.2003
Откуда: South Ural
Ray Adams
проверять стоит для самого плохого случая - сравни один и тотже блок памяти с самим собой со сдвигом на дворд :)

_________________
http://stargaz0r.nm.ru
http://people.overclockers.ru/StarGaz0r/files


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
stargaz0r не совсем понял как именно это сделать :)
может модифицировать стандартную процедуру?
Код:
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
        PUSH    ESI
        PUSH    EDI
        MOV     ESI,P1
        MOV     EDI,P2
        MOV     EDX,ECX
        XOR     EAX,EAX
        AND     EDX,3
        SAR     ECX,2
        JS      @@1     // Negative Length implies identity.
        REPE    CMPSD
        JNE     @@2
        MOV     ECX,EDX
        REPE    CMPSB
        JNE     @@2
@@1:    INC     EAX
@@2:    POP     EDI
        POP     ESI
end;


 

Member
Статус: Не в сети
Регистрация: 23.09.2003
Откуда: South Ural
Ray Adams
ну к примеру если p1=$a000 то p2=$a004
можно и модифицировать - заметь - repe cmpsd - как я и предлагал :)

_________________
http://stargaz0r.nm.ru
http://people.overclockers.ru/StarGaz0r/files


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Да кстати вот это не верно
inc(integer(p1), 4);
inc(integer(p2), 4);
надо
inc(dword(p1));
inc(dword(p2));


 

Member
Статус: Не в сети
Регистрация: 23.09.2003
Откуда: South Ural
Ray Adams
ну если ты собрался сравнивать дворды побайтно, то конечно :D

_________________
http://stargaz0r.nm.ru
http://people.overclockers.ru/StarGaz0r/files


 

Advanced member
Статус: Не в сети
Регистрация: 13.04.2003
Откуда: Салават
Чисто навскидку
Цитата:
inc(integer(p1), 4);
inc(integer(p2), 4);
dec(size);


лучше заменить на add и sub, они на P4 быстрее исполняются AFAIK

Цитата:
REPE CMPSD


то же самое, на современных процессорах аналог из простых команд будет быстрее

все адреса переходов выравнять по 16-байтной границе

_________________
О браузерах без субъективизма http://people.overclockers.ru/GReY/16906/Obektivnyj_test_brauzerov


 

Member
Статус: Не в сети
Регистрация: 23.09.2003
Откуда: South Ural
GReY
Цитата:
лучше заменить на add и sub, они на P4 быстрее исполняютс

делфи это как раз в add и sub компилирует :)

Цитата:
все адреса переходов выравнять по 16-байтной границе

на basm это трудновыполнимо

_________________
http://stargaz0r.nm.ru
http://people.overclockers.ru/StarGaz0r/files


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 14 
-

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan