Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Вниз

Поиск в бинарном файле   Найти похожие ветки 

 
Defunct ©   (2004-09-27 22:19) [80]

GuAV ©   (27.09.04 21:38) [77]
> Repe CmpsD, а CmpsB - остаток

Уже рассматривал, этот вариант. Мне не хватает одного РОНа, чтобы сделать с CmpsD. Приходится юзать стек, значительно проиграем на коротких строках. либо придется использовать регисты MM0-MMX, тада возможен, как тут любят выражаться, "гимор" если в программе была арифметика с плавающей точкой.

> заблуждаетесь.
Возможно, а возможно и нет, читал совсем недавно 1-2 месяца назад, в справке по Delphi тока не помню где именно (удивлялся). Там еще были примеры с приведением типов Integer -> Boolean, Boolean -> Integer, Boolean -> Byte, Byte -> Boolean, и вот осело в памяти $FFFFFFFF = True. Так или иначе, это не имеет значения, т.к. проверка на True все равно делается командой Test(будь там -1 или +1 результат не изменится, а по скорости Dec и Inc идентичны)

Test Reg,Reg
Jnz  @@True

PS: могу попробовать сделать поиск с использованием MMX если найду время.


 
Defunct ©   (2004-09-27 22:23) [81]

GuAV ©   (27.09.04 22:08) [79]
не столь важно, поймите я не хочу вас оскорбить или сказать, что вы плохо разбираетесь в асме, просто заметил ошибку, исправил привел вариант [74] так что не зацикливайтесь на одном месте. Хотите продолжить оптимизацию, продолжайте с [74]


 
GuAV ©   (2004-09-27 22:26) [82]


> результат поиска строки "01wbcb" в файле gladiator.avi (726Mb)
> с учетом что такой строки в файле нет, а есть множество
> строк "01wb" составил - 22.34 сек, при повторном запуске
> - 13.71 сек. проверял на компе с 512Mb памяти (т.е. файл
> не мог полностью разместиться в кеше).

Это мысль ! Буфер надо не 1ГБ а где-то 16..32 кБ


 
GuAV ©   (2004-09-27 22:32) [83]


> Так или иначе, это не имеет значения, т.к. проверка на True
> все равно делается командой Test(будь там -1 или +1 результат
> не изменится, а по скорости Dec и Inc идентичны)

Не всегда, на пример я сослался в
GuAV ©   (27.09.04 13:01) [68]
т.е. с Boolean вольности не допускаются

> Возможно, а возможно и нет, читал совсем недавно 1-2 месяца
> назад, в справке по Delphi тока не помню где именно (удивлялся).
> Там еще были примеры с приведением типов Integer -> Boolean,
> Boolean -> Integer, Boolean -> Byte, Byte -> Boolean, и
> вот осело в памяти $FFFFFFFF = True.

Ну, в книгах бывают опечатки. Я думал тоже в EAX Integer-результат всегда, а оказывается к safecall это неприменимо.

$FFFFFFFF = True
Насколько я поню, это так в VisualBasic

в Delphi SizeOf(Boolean) = 1 байт. ord(True)=1

есть типы ByteBool, LongBool, WordBool в которых допускаются вольности по части ord(True). в Window.pas кажется или ещё где то объявлен тип BOOL=LongBool


 
GuAV ©   (2004-09-27 22:50) [84]

Раз возвращаете Integer, возвращайте уже позицию в файле.

Function ConstantExists(FileName, Constant: String): Int64;
Var
 Buffer  : PBuffer;
 F       : File;
 BufSize : Integer;
 BufPos  : Integer;
Begin
 Result:=0;
 New(Buffer);
 try
   AssignFile(F, FileName);
   Reset(F,1);
   try
     Repeat
       BlockRead(F, Buffer^, MaxBufferSize, BufSize);
       If BufSize < Length(Constant) Then Break;
       BufPos := ConstantPos(Constant, Buffer, BufSize);
       if BufPos > 0 then
       begin
         Inc(Result, BufPos);
         Exit;
       end;
       Inc(Result, BufSize);
       Seek(F, FilePos(F) - Length(Constant));
     Until (BufSize<MaxBufferSize);
     Result := -1;
   finally
     CloseFile(F);
   end;
 finally
   Dispose(Buffer);
 end;
End;


> Буфер надо не 1ГБ а где-то 16..32 кБ

вечер плохого дня...


 
GuAV ©   (2004-09-27 22:59) [85]


>  if BufPos > 0 then

BufPos => 0 или BufPos <> -1.


 
GuAV ©   (2004-09-27 23:03) [86]

такой вариант принимается ?

@@CompareWholeString:
 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  ECx, 2       // ECx - constant chars amount div 4
 Repe CmpsD
 Jz   @@Constant_Exists
 Mov  ECx, Ebx
 and  ECx, 3
 Repe CmpsB
 Jz   @@Constant_Exists

или наоборот, сначала B а потом D
 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  EBx, 2       // EBx - constant chars amount div 4
 and  ECx, 3
 Repe CmpsB
 Jz   @@Constant_Exists
 Mov  ECx, Ebx
 Repe CmpsD
 Jz   @@Constant_Exists


 
Defunct ©   (2004-09-27 23:13) [87]

[84]
Поправлю, вы забыли учесть откат на Length(Constant):

Function ConstantExists(FileName, Constant: String): Int64;
Var
Buffer  : PBuffer;
F       : File;
BufSize : Integer;
BufPos  : Integer;
Begin
BufPos := -1;
New(Buffer);
try
  AssignFile(F, FileName);
  Reset(F,1);
  try
    Repeat
      Result := FilePos(F);
      BlockRead(F, Buffer^, MaxBufferSize, BufSize);
      If BufSize >= Length(Constant) Then
      BufPos := ConstantPos(Constant, Buffer, BufSize);
      Result := Result + BufPos;
      Seek(F, FilePos(F) - Length(Constant));
    Until (BufPos>0) or (BufSize<MaxBufferSize);
  finally
    CloseFile(F);
  end;
finally
  If BufPos < 0 Then Result := -1;
  Dispose(Buffer);
end;
End;


 
GuAV ©   (2004-09-27 23:26) [88]


>       If BufSize >= Length(Constant) Then
>       BufPos := ConstantPos(Constant, Buffer, BufSize);
>       Result := Result + BufPos;

Result будет накапливать -1.


 
GuAV ©   (2004-09-27 23:29) [89]


> Поправлю, вы забыли учесть откат на Length(Constant):

Тогда
Function ConstantExists(FileName, Constant: String): Int64;
Var
Buffer  : PBuffer;
F       : File;
BufSize : Integer;
BufPos  : Integer;
Begin
New(Buffer);
try
  AssignFile(F, FileName);
  Reset(F,1);
  try
    Repeat
      Result := FilePos(F);
      BlockRead(F, Buffer^, MaxBufferSize, BufSize);
      If BufSize < Length(Constant) Then Break;
      BufPos := ConstantPos(Constant, Buffer, BufSize);
      if BufPos > 0 then
      begin
        Inc(Result, BufPos);
        Exit;
      end;
      {Inc(Result, BufSize);}
      Seek(F, FilePos(F) - Length(Constant));
    Until (BufSize<MaxBufferSize);
    Result := -1;
  finally
    CloseFile(F);
  end;
finally
  Dispose(Buffer);
end;
End;


 
Defunct ©   (2004-09-27 23:38) [90]

GuAV ©   (27.09.04 23:03) [86]
принимается с поправками, а то получим нехилую ошибку при Length(Constant)<=6 и при (Length(Constant)) mod 4 = 0.


@@CompareWholeString:
  Mov  ECx, Ebx       // ECx - constant chars amount
  shr  ECx, 2         // ECx - constant chars amount div 4
  jz   @@SkipDTest
  Repe CmpsD
  Jnz  @@SkipBTest
@@SkipDTest:  
  Mov  ECx, Ebx
  and  ECx, 3
  jz   @@SkipBTest
  Repe CmpsB
  Jz   @@Constant_Exists
@@SkipBTest:
  Mov  ESi, EBp       // restore pointer to 2nd char of constant


В общем, получилось просто отлично. на том же файле (gladiator.avi) строка поиска ("01wbcb") время просмотра всего файла - 13.43 сек (было 13.71). Для больших строк конечно же ускорение будет выше.

Попробовал поиграться с размером буфера:
- 10MB скорость падает
- делаю 512Kb - скорость падает.
(Кеш L2 у меня 1Mb) потому 1Mb - оптимально как для машины на которой проводил тесты.


 
Defunct ©   (2004-09-27 23:45) [91]

GuAV ©   (27.09.04 23:26) [88]

Дык, в секции finally посмотрите If bufpos<0....
и сброс перед поиском Result := FilePos


 
GuAV ©   (2004-09-27 23:57) [92]

 Mov  ECx, Ebx       // ECx - constant chars amount
 shr  ECx, 2         // ECx - constant chars amount div 4
 jz   @@SkipDTest
 Repe CmpsD
 Jnz  @@SkipBTest
@@SkipDTest:  
 Mov  ECx, Ebx
 and  ECx, 3
 jz   @@Constant_Exists // two least significant bits
                        // of amount is zero so the Constant matches

 Repe CmpsB
 Jz   @@Constant_Exists
@@SkipBTest:

?


 
GuAV ©   (2004-09-27 23:58) [93]

сорри, Ж нажал вместо КОД
Mov  ECx, Ebx       // ECx - constant chars amount
shr  ECx, 2         // ECx - constant chars amount div 4
jz   @@SkipDTest
Repe CmpsD
Jnz  @@SkipBTest
@@SkipDTest:  
Mov  ECx, Ebx
and  ECx, 3
jz   @@Constant_Exists // two least significant bits
                       // of amount is zero so the Constant
matches
Repe CmpsB
Jz   @@Constant_Exists
@@SkipBTest:

принято ?


 
GuAV ©   (2004-09-28 00:09) [94]


> GuAV ©   (27.09.04 23:26) [88]
>
> Дык, в секции finally посмотрите If bufpos<0....
> и сброс перед поиском Result := FilePos

ок.
Всё же вариант [89] ничем не хуже, только проще.

 If BufPos < 0 Then Result := -1;
кстати подобный код следует размещать после until перед finally, но не в finally. дело в том, что в случае отсутствия исключения он и так выполнится. в случае исключения результат функции не нужен, более того я даже не вижу возможности им воспользоваться.


 
Defunct ©   (2004-09-28 00:32) [95]

GuAV ©   (27.09.04 23:58) [93]
конечно принято!

GuAV ©   (28.09.04 00:09) [94]
> в случае исключения результат функции не нужен
почему бы не перестраховаться. пусть возвращает правильный результат даже в исключительной ситуации. (нам тока спасибо скажут)

> более того я даже не вижу возможности им воспользоваться.
А я вижу, когда "наплевать" на исключения, их просто проигнорируют, а результат функции будет верным.
Тока не надо говорить, что так делать не правильно, сам знаю, но все равно делаю ;)


 
GuAV ©   (2004-09-28 00:38) [96]


> > более того я даже не вижу возможности им воспользоваться.
> А я вижу, когда "наплевать" на исключения, их просто проигнорируют,
> а результат функции будет верным.
> Тока не надо говорить, что так делать не правильно, сам
> знаю, но все равно делаю ;)


например если
I:=MyFunc
и в MyFunc - исключение, то в I остаётся старое значение

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


 
Defunct ©   (2004-09-28 00:56) [97]

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

Беру функцию [87]

Использую ее так:

procedure TForm1.Button1Click(Sender: TObject);
Var Position : Int64;
begin
Try
  Position := ConstantExists(Edit1.Text, Edit2.Text);
Except
End;

If Position>0 Then
   ShowMessage("Found")
Else
   ShowMessage("Not Found");
End;
end;

В Edit1 ввожу какую-то лабуду типа "sdfsdf.asdasd" в Edit2 - "Test String" возникает исключение на экране вижу "Not Found". Хотя понятно, тест синтетический проще было бы в обработчике исключения написать, что файла с таким именем нет. ;)


 
GuAV ©   (2004-09-28 00:59) [98]

Defunct ©   (28.09.04 00:56) [97]
Это похоже на уровне "повезло", попробуйте
Var Position : Int64; - глобальная переменная.


 
Defunct ©   (2004-09-28 01:00) [99]

PS: код [97] серьезно не воспринимать, правильно должно быть так:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Try
   If ConstantExists(Edit1.Text, Edit2.Text)>0 Then
      ShowMessage("Found")
   Else
      ShowMessage("Not Found");
 Except
   ShowMessage("file "+Edit1.Text+" not found");
 End;
end;


 
Defunct ©   (2004-09-28 01:03) [100]

GuAV ©   (28.09.04 00:59) [98]
Ок, убедили, признаю - страдать фигней незачем.


 
GuAV ©   (2004-09-28 01:21) [101]

знаете, как можно узнать про флаг D, отсутсвие результата при exception и т.д. ?
посмотреть исходники VCL, найти места где Вы не согласны с Borland и разобраться почему они всё же правы.

см. мою анкету -
F1 - интересно, Ctrl+Click - ещё интереснее,

Defunct ©   (28.09.04 01:00) [99]
на самом деле, лучше вообще без except. тогда будет выведен текст исключения в сообщении, почему именно не получилось. может не файл не найден а ещё что-то. хотя бы EOutOfMemory.

или уже например что-то типа
Try
  If ConstantExists(Edit1.Text, Edit2.Text)>0 Then
     ShowMessage("Found")
  Else
     ShowMessage("Not Found");
Except
  on EInOutError do ShowMessage("file "+Edit1.Text+" not found");
End;

except без on следует использовать только если внутри raise; - т.е. исключение сохранится для дальнейшего использования.


 
Defunct ©   (2004-09-28 02:29) [102]

> найти места где Вы не согласны с Borland и разобраться почему они всё же правы.

Знаете, не надо так свято верить в правоту Borland, функция [74] - быстрее Pos, а та к которой мы с вами в итоге пришли после усовершенствования [74] работает более чем в два раза быстрее чем встроенная функция поиска подстроки в строке: Pos. И это не первая функция на моем счету, которая доказывает, что не все решения от Borland оптимальны.

> F1 - интересно, Ctrl+Click - ещё интереснее,
Хелп сделан хорошо, здесь упреков нет.

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

> почему именно не получилось. может не файл не найден а ещё что-то. хотя бы EOutOfMemory.

Ну что ж тогда увы и ах..:
<begin offtop>
.. в одном отдаленном селе Василий Певченко скачал шареварную версию нового "PuperCommander". С возгласом:
- ну наконец-то, догожданная новая версия,
Василий принялся изучать Readme файл со списоком новых возможностей и улучшений...
- О! быстрый поиск строки, сейчас посмотрю, что они там намутили, - улыбнулся Василий, который несколько лет ждал именно эту фичу.
Он задавал имя файла и ввел "смешные анеГДОТЫ" в раскрашенном поле строки поиска, к его глубочайшему удивлению на экране возникало сообщение "Да ну нет такого файла!". Василий повторял ввод имени раз за разом, раз за разом, но на экране в также весело красовалась пестрая надпись с заголовком PuperCommander, уведомляющая, что такого файла нет. Василий вспомнил, что вчера выпил не мало, об этом напиминали трясущиеся руки, и решил скопировать имя файла прямо из проводника самой модной операционки "ГунДоус" от корпорации "МодныйСофт". А на экране все также пестрилась веселая надпись "Да не найден, надо меньше пить". В гневе Василий нажал кнопку "ПЫтание" на корпусе своего модного компутера "ИВМ" от фирмы "Красночух Электроникс", замигали лампочки, в динамиках раздался приятный женский голос "подождите пожалуйста, ГунДоус приступил к первой фазе подготовки к выполнению завершения вашей работы". Василий ждал..
.....
...
..
Экран засветился, потом погас, потом опять засветился на этот раз с надписью "Красночух Электроникс БИОС, ждите", замигали лампочки. Василий потихоньку приходил в себя, он взял очередную бутылочку пива из холодильника и удобно развалился на кресле с мягкой спинкой. Наблюдая за меняющимися картинками, которыми обычно сопровождается загрузка модной системы "ГунДоус", он размышлял о том, что он самый счастливый человек на свете. Теперь у него есть "PuperCommander" и он сможет с гордостью похвастаться об этом своим друзьям. "ГунДоус" пригласил Василия ввести пароль, после чего Василий сразу же запустил "PuperCommander" ввели имя файла и.... О чудо! ни каких надписей, пестрая табличка с вопросом "смешные анеГДОТЫ найдены, показать?".
- Глючный ГунДоус, - подумал Василий, - когда уже эти олухи из корпорации "МодныйСофт" сделают что-то нормальное..
<end offtop>

И в чем-то Василий будет прав.
В данном конкретном случае меня не интересуют другие ошибки кроме "файл не найден" так как логически там их быть не может, кроме случая - ошибка ОС.


 
jack128 ©   (2004-09-28 02:42) [103]

Defunct ©   (28.09.04 2:29) [102]
работает более чем в два раза быстрее чем встроенная функция поиска подстроки в строке:


Ага, сели два чела, 4 дня провозились и еще и удивляются, как же у них получилась функция, которая быстрее стандартной реализации ;-)

зы Pos - не ориентирован на поиск подстроки в 1Гб файле. Насколько она быстрее при работе с обычными строками (длиной 30-100 символов)
ззы вашу функцию нужно в базу знаний отправить.


 
Defunct ©   (2004-09-28 03:06) [104]

> Насколько она быстрее при работе с обычными строками (длиной 30-100 символов)

Pos будет медленнее, так как в стадартной функции Pos две пары Push/Pop в основном цикле поиска и не рассмотривается вариант отбраковки подстроки по первому и последнему символам.

На сколько медленнее сказать сейчас не могу. На маленьких строках тяжело точно измерить скорость, куча побочных эффектов, например, просто факт вызова функции (команда Call) отнимает примерно столько времени сколько потребуется на просмотр 2-5 символов, согласитесь немало при длинне строки в 30 символов.


 
Defunct ©   (2004-09-28 10:46) [105]

2 GuruAV.

Подумайте как можно применить следущее:
скажем есть возможность получать такие последовательности (команда PCMPEQB mmreg, mmreg/rel32}
на входе:
->
  54h 34h 34h 45h 35h 43h 64h 70h 65h 70h
  34h 34h 34h 34h 34h 34h 34h 34h 34h 34h


на выходе:
<-
  00h FFh FFh 00h 00h 00h 00h 00h 00h 00h


за один такт.

  Как бы это применить к нашему сабжу.. Хочется избавиться от ScasB


 
Defunct ©   (2004-09-28 11:49) [106]

вот наброски, черт его знает стоит ли оно того, что-то уж сильно много кода получается


  ...
{$ifdef MMX}
  MovQ  MM0, [Edi]    // load prefics
  PCMPEQB MM0, MM6    // make a mask (mm6 filled by 1st char of da constant)
  MovD  EAx, MM0
  Test  EAx,EAx
  Jnz   @@Char_somewhere??
  PSRLQ MM0,32        // mm0 := mm0 div 2^32
  MovD  EAx, MM0
  Test  EAx, EAx
  Jnz   @@Char_Somewhere??
  Add   EDi,8
  Sub   ECx,8
  Jns   @@Scan
{$else}
  Repne ScasB
{$endif}
  ...
  ...

@@Leave_Proc:
{$ifdef MMX}
  EMMS
{$endif}


 
Игорь Шевченко ©   (2004-09-28 12:30) [107]

MMF оно проще...


 
Sha ©   (2004-09-28 12:34) [108]

Ага, никакого буфера.
И простым циклом на Паскале.


 
GuAV ©   (2004-09-28 22:12) [109]


> И это не первая функция на моем счету, которая доказывает,
> что не все решения от Borland оптимальны.

Однако они почти все верны. Т.к. умные люди писали и их очень многие используют.
Ну могут быть и не оптимальны, т.к. они и не особо стремятся - они вероятно такой фигнёй не страдают.


> Это уж кому как, я предпочту чтобы программа умолчала об
> исключении вместо того чтобы показала, что исключение в
> ней не обрабатывается.

Ну вот допустим памяти не хватило. Тогда файл не найден.
А он не найден потому что его нет или памяти нехватило, или ошибка чтения файла - угадай-ка ? :)
Если же речь идет об ошибке ОС, то показ текста выданого самой ОС - ИМХО лучшая обработка.


> меня не интересуют другие ошибки кроме "файл не найден"
> так как логически там их быть не может, кроме случая - ошибка
> ОС

Может и не интересуют, но они могут в принципе быть.
И потом, ошибка файл не найден должна обрабатываться не этой функцией, а вызывающей её функцией и если хотите всё же её обрабатывать, то GuAV ©   (28.09.04 01:21) [101] .

Ошибки могут быть даже там где их логически быть не может.

jack128 ©

> Ага, сели два чела, 4 дня провозились и еще и удивляются,
> как же у них получилась функция, которая быстрее стандартной
> реализации ;-)

я вообще-то не особо возился :) заметь, несмотря на то что я поставил Дельфи, я ни разу не выполнял этот код. Так чит
Поэтому больше благодари Defunct ©


> ззы вашу функцию нужно в базу знаний отправить.

Почему-то мне кажется что там такое уже есть.
Если конечно Defunct © напишет версию через продвинутый набор комманд, то этой может там ещё не быть.

Кстати, согласно моей информации (изрядно впрочем устаревшей), MOV и PUSH работают одинаково быстро (если в качестве операнда push РОН). XCHG же работает медленнее. Может на современных процессорах это не так, тогда был бы рад информации.

PUSH  reg16   ¦ push  dx                ¦ 88/86 11 (88=15)
PUSH  reg32*  ¦                         ¦   286 3
PUSHW reg16   ¦                         ¦   386 2
PUSHD reg16*  ¦                         ¦   486 1
PUSHD reg32*  ¦                         ¦

MOV  reg,reg        ¦ mov   dh,bh             ¦ 88/86 2
                   ¦ mov   dx,cx             ¦   286 2
                   ¦ mov   bp,sp             ¦   386 2
                   ¦                         ¦   486 1

XCHG  reg,reg       ¦ xchg   cx,dx        ¦ 88/86 4
                    ¦ xchg   dl,dh        ¦   286 3
                    ¦ xchg   al,ah        ¦   386 3
                    ¦                     ¦   486 3



> MMF оно проще...

- Cолдаты! берите ломы и копайте яму 2 на 2!
- Товарищь прапорщик, а не лучше ли взять лопаты?
- А мне не нужно лучше, мне нужно чтоб вы за... (замучились) !


 
Defunct ©   (2004-09-29 02:06) [110]

XCHG  reg32,reg32       ¦ xchg   eax,edx        ¦ P-Pro and higher - 1/2


 
Fedia   (2004-09-29 02:56) [111]

To Defunct and GuAV.
Даже несмотря на то, что большинство кода на ASM для меня оставалось загадкой, все равно с удовольствием почитал ветку.
А итоговую процедуру поиска с удовольствием буду использовать.
Просто хотел поблагодарить GuAV за настойчивость, а Defunct за терпение :)


 
Defunct ©   (2004-09-29 03:23) [112]

Кому интересно, поиск строки с использованием MMX. Ускорен поиск на 10-20% (скорость зависимосит от частоты появлнеия первого символа искомой строки в буфере поиска). Результат пересмотра буфера объемом- 2.5Gb (25Mb 100 раз подряд) составляет 9.123 сек, в то время как без MMX - 10.238 сек.

{$define MMX}

Function ConstantPos(const Constant: string;
 Buffer: Pointer; BufSize: Integer): Integer; Assembler;
Asm
  Push EDi
  Push ESi
  Push EBx
  Push EBp
  Push ECx            // store total buffer size for later calculation pos
  MOV  ESI, EAX       // ESi pointer to constant
  Mov  EDi, EDx       // EDi pointer to buffer
  Mov  Al, [ESi]      // Store first char of the constant in AL
  Mov  EBX, [ESI-4]
  Dec  EBX
{$ifdef MMX}
  Mov  Ah, Al         // Spreading char to 32bit register
  Push Ax
  Push Ax
  Pop  EAx
  MovD MM6, EAx
  PSLLQ MM6,MM6       // Spreading char to mmx register
  PXOR  MM5,MM5       // Z mask for later calculations
  MovD MM6, EAx
{$endif}
  Mov  Ah, [ESi+EBx]  // Store last char of the constant in AH
  Dec  EBx            // EBx - length of the constant w/o 1st and last chars
  Mov  EDx,ECx        // EDx - Stored residual buffer size
  Inc  ESi
  Mov  EBp, ESi       // EBp - stored pointer to 2nd char of constant

{$ifdef MMX}
  MovD MM4, EAx       // store EAx in MM buffer
{$endif}

@@Scan:
{$ifdef MMX}
  MovQ      MM7, [Edi]  // load a part of buffer that needs to be scaned
  PCMPEQB   MM7, MM6    // make a bit mask (mm6 filled by 1st char of da constant)
  PCMPGTD   MM7, MM5    // make a dword mask
  PUNPCKHBW MM7, MM7    // mix 2 dwords into a qword
  MovD      EAx, MM7    // get mixed dword
  Test  EAx, EAx        // was there at least 1 bit set?
  Jnz   @@CharFound     // yes - 1st char of the constant was found
  Add   EDi,8           // correct index
  Sub   ECx,8           // and buffer size
  Jns   @@Scan          // continue scan if buffer not empty
  Jmp   @@Exit_False    // otherwise - leave with no result
@@CharFound:
  MovD  EAx, MM4        // restore EAx (1st and last chars of the constant)
{$endif}
  Repne ScasB
  JNE   @@Exit_False  // no 1st char of the constant found = exit_false
  Mov   EDx, ECx      // store new residual buffer size
  Cmp   EDx, EBx      // constant still can be settled in buffer
  Ja    @@CheckLastChar  // no - exit with false result

@@Exit_False:
  Pop  EAx
  Xor  EAx,EAx        // False = (0), check delphi help for more info
  Dec  EAx
  Jmp  @@Leave_Proc

@@CheckLastChar:      // as proposed in Boyer-Mur alhorithm

  Cmp   Ah, [EDi+EBx] // check found substring with last char of the constant
  Jnz   @@Scan        // not match - continue searching

@@CompareWholeString:

  Mov  ECx, Ebx       // ECx - constant chars amount
  shr  ECx, 2         // ECx - constant chars amount div 4
  jz   @@SkipDTest
  Repe CmpsD
  Jnz  @@SkipBTest
@@SkipDTest:
  Mov  ECx, Ebx
  and  ECx, 3
  jz   @@Constant_Exists // two least significant bits
                      // of amount are zero so the Constant matches
  Repe CmpsB
  Jz   @@Constant_Exists
@@SkipBTest:

  Mov  ESi, EBp       // restore pointer to 2nd char of constant
  Add  EDx, ECx
  Sub  EDx, EBx       // correct residual buffer size
  Mov  ECx, EDx       // restore residual buffer size to ECx

  Jnz  @@Scan

@@Constant_Exists:
  Pop  EAx
  Sub  EAx, EDx

@@Leave_Proc:
{$ifdef MMX}
  EMMS                // finish mmx operations
{$endif}

  Pop  EBp
  Pop  EBx
  Pop  ESi
  Pop  EDi
End;


 
Defunct ©   (2004-09-29 03:36) [113]

> - А мне не нужно лучше, мне нужно чтоб вы за... (замучились) !

Отож простые задачи - неитересны, и даже скучны.


 
Defunct ©   (2004-09-29 04:30) [114]

Так работает немножко быстрее, на 0.5-1%

  ...
{$ifdef MMX}
  MovQ      MM7, [Edi]  // load a part of buffer that needs to be scaned
  PCMPEQB   MM7, MM6    // make a bit mask (mm6 filled by 1st char of da constant)
  PCMPGTD   MM7, MM5    // make a dword mask
  PUNPCKHWD MM7, MM7    // mix 2 dwords into a qword
  ...
  ...
   
{$endif}

  Repne ScasB
{$ifndef MMX}
  JNE   @@Exit_False  // no 1st char of the constant found = exit_false
{$endif}
  ...


>> меня не интересуют другие ошибки кроме "файл не найден"
>> так как логически там их быть не может, кроме случая - ошибка
>> ОС

> Может и не интересуют, но они могут в принципе быть.

> Ну вот допустим памяти не хватило. Тогда файл не найден.
> А он не найден потому что его нет или памяти нехватило, или
> ошибка чтения файла - угадай-ка ? :)


PS: GuruAV как вам рассказик [102]? там все сказано об этом.


 
Defunct ©   (2004-09-29 04:50) [115]

> Ну могут быть и не оптимальны, т.к. они и не особо стремятся - они вероятно такой фигнёй не страдают.

Вот потому все серьезные проекты, которые требуют скорости и пишутся на C++, а компилируются или MS Visual Studio .Net или интеловский компилятором.


 
Игорь Шевченко ©   (2004-09-29 10:22) [116]


> Вот потому все серьезные проекты, которые требуют скорости
> и пишутся на C++, а компилируются или MS Visual Studio .Net
> или интеловский компилятором.


Лажу гнать не надо, а ?


 
Defunct ©   (2004-09-29 18:14) [117]

Игорь Шевченко ©   (29.09.04 10:22) [116]

в чем лажа?


 
GuAV ©   (2004-09-29 22:10) [118]


> PS: GuruAV как вам рассказик [102]? там все сказано об этом.

Не понял что Вы хотели им сказать. Однако
[101] и
> Может и не интересуют, но они могут в принципе быть.

> Ну вот допустим памяти не хватило. Тогда файл не найден.
> А он не найден потому что его нет или памяти нехватило, или
> ошибка чтения файла - угадай-ка ? :)

в силе.

Defunct ©   (29.09.04 03:23) [112]
c00l !
Напишите ещё и {$else} и выделите не MMX код туда, а то совсем прочитать не могу


 
Defunct ©   (2004-09-29 23:16) [119]

> Напишите ещё и {$else} и выделите не MMX код туда, а то совсем прочитать не могу

Не, там все должно быть как есть. с помощью MMX делается только определение наличия символа в QWORD, дальше repne scas просматривает только цепочку из 8-ми байт.

Из старого кода выбрасывается только одна команда, смотреть поправку [114] секция {$ifndef}

Уберете {define MMX} будет работать старая функция, оставите - будет сканироваться по 8 байт.


 
Sha ©   (2004-09-30 09:24) [120]

> Defunct

Попробуй написать аналог Борландовской Pos на базе своей функции и померяйся с вот этим:

//(c) John O"Harrow
function PosJOH_MMX(const SubStr : AnsiString; const Str : AnsiString) : Integer;
asm
 test      eax, eax
 jz        @NotFoundExit    {Exit if SurStr = ""}
 test      edx, edx
 jz        @NotFound        {Exit if Str = ""}
 mov       ecx, [edx-4]     {Length(Str)}
 cmp       [eax-4], 1       {Length SubStr = 1?}
 je        @SingleChar      {Yes - Exit via CharPos}
 jl        @NotFound        {Exit if Length(SubStr) < 1}
 sub       ecx, [eax-4]     {Subtract Length(SubStr), -ve handled by
CharPos}
 add       ecx, 1           {Number of Chars to Check for 1st Char}
 push      esi              {Save Registers}
 push      edi
 push      ebx
 push      ebp
 mov       esi, eax         {Start Address of SubStr}
 mov       edi, ecx         {Initial Remainder Count}
 mov       eax, [eax]       {AL = 1st Char of SubStr}
 mov       ebp, edx         {Start Address of Str}
 mov       ebx, eax         {Maintain 1st Search Char in BL}
@StrLoop:
 mov       eax, ebx         {AL  = 1st char of SubStr}
 mov       ecx, edi         {Remaining Length}
 push      edx              {Save Start Position}
 call      @CharPos         {Search for 1st Character}
 pop       edx              {Restore Start Position}
 test      eax, eax         {Result = 0?}
 jz        @StrExit         {Exit if 1st Character Not Found}
 mov       ecx, [esi-4]     {Length SubStr}
 add       edx, eax         {Update Start Position for Next Loop}
 sub       edi, eax         {Update Remaining Length for Next Loop}
 sub       ecx, 1           {Remaining Characters to Compare}
@StrCheck:
 mov       al, [edx+ecx-1]  {Compare Next Char of SubStr and Str}
 cmp       al, [esi+ecx]
 jne       @StrLoop         {Different - Return to First Character Search}
 sub       ecx, 1
 jnz       @StrCheck        {Check each Remaining Character}
 mov       eax, edx         {All Characters Matched - Calculate Result}
 sub       eax, ebp
@StrExit:
 pop       ebp              {Restore Registers}
 pop       ebx
 pop       edi
 pop       esi
 ret
@NotFound:
 xor       eax, eax         {Return 0}
@NotFoundExit:
 ret
@SingleChar:
 mov       al, [eax]        {Search Character}
@CharPos:
 CMP       ECX, 8
 JG        @@NotSmall
@@Small:
 or        ecx, ecx
 jle       @@NotFound       {Exit if Length <= 0}
 CMP       AL, [EDX]
 JZ        @Found1
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+1]
 JZ        @Found2
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+2]
 JZ        @Found3
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+3]
 JZ        @Found4
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+4]
 JZ        @Found5
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+5]
 JZ        @Found6
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+6]
 JZ        @Found7
 DEC       ECX
 JZ        @@NotFound
 CMP       AL, [EDX+7]
 JZ        @Found8
@@NotFound:
 XOR       EAX, EAX
 RET
@Found1:
 MOV       EAX, 1
 RET
@Found2:
 MOV       EAX, 2
 RET
@Found3:
 MOV       EAX, 3
 RET
@Found4:
 MOV       EAX, 4
 RET
@Found5:
 MOV       EAX, 5
 RET
@Found6:
 MOV       EAX, 6
 RET
@Found7:
 MOV       EAX, 7
 RET
@Found8:
 MOV       EAX, 8
 RET

@@NotSmall:                  {Length(Str) > 8}
 MOV       AH, AL
 ADD       EDX, ECX
 MOVD      MM0, EAX
 PUNPCKLWD MM0, MM0
 PUNPCKLDQ MM0, MM0
 PUSH      ECX              {Save Length}
 NEG       ECX
@@First8:
 MOVQ      MM1, [EDX+ECX]
 ADD       ECX, 8
 PCMPEQB   MM1, MM0         {Compare All 8 Bytes}
 PACKSSWB  MM1, MM1         {Pack Result into 4 Bytes}
 MOVD      EAX, MM1
 TEST      EAX, EAX
 JNZ       @@Matched        {Exit on Match at any Position}
 CMP       ECX, -8          {Check if Next Loop would pass String End}
 JGE       @@Last8
@@Align:                     {Align to Previous 8 Byte Boundary}
 LEA       EAX, [EDX+ECX]
 AND       EAX, 7           {EAX -> 0 or 4}
 SUB       ECX, EAX
@@Loop:
 MOVQ      MM1, [EDX+ECX]
 ADD       ECX, 8
 PCMPEQB   MM1, MM0         {Compare All 8 Bytes}
 PACKSSWB  MM1, MM1         {Pack Result into 4 Bytes}
 MOVD      EAX, MM1
 TEST      EAX, EAX
 JNZ       @@Matched        {Exit on Match at any Position}
 CMP       ECX, -8          {Check if Next Loop would pass String End}
{$IFNDEF NoUnroll}
 JGE       @@Last8
 MOVQ      MM1, [EDX+ECX]
 ADD       ECX, 8
 PCMPEQB   MM1, MM0         {Compare All 8 Bytes}
 PACKSSWB  MM1, MM1         {Pack Result into 4 Bytes}
 MOVD      EAX, MM1
 TEST      EAX, EAX
 JNZ       @@Matched        {Exit on Match at any Position}
 CMP       ECX, -8          {Check if Next Loop would pass String End}
{$ENDIF}
 JL        @@Loop
@@Last8:
 MOVQ      MM1, [EDX-8]     {Position for Last 8 Used Characters}
 POP       EDX              {Original Length}
 PCMPEQB   MM1, MM0         {Compare All 8 Bytes}
 PACKSSWB  MM1, MM1         {Pack Result into 4 Bytes}
 MOVD      EAX, MM1
 TEST      EAX, EAX
 JNZ       @@Matched2       {Exit on Match at any Position}
 EMMS
 RET                        {Finished - Not Found}
@@Matched:                   {Set Result from 1st Match in EDX}
 POP       EDX              {Original Length}
 ADD       EDX, ECX
@@Matched2:
 EMMS
 SUB       EDX, 8           {Adjust for Extra ADD ECX,8 in Loop}
 TEST      AL, AL
 JNZ       @@MatchDone      {Match at Position 1 or 2}
 TEST      AH, AH
 JNZ       @@Match1         {Match at Position 3 or 4}
 SHR       EAX, 16
 TEST      AL, AL
 JNZ       @@Match2         {Match at Position 5 or 6}
 SHR       EAX, 8
 ADD       EDX, 6
 JMP       @@MatchDone
@@Match2:
 ADD       EDX, 4
 JMP       @@MatchDone
@@Match1:
 SHR       EAX, 8           {AL <- AH}
 ADD       EDX, 2
@@MatchDone:
 XOR       EAX, 2
 AND       EAX, 3           {EAX <- 1 or 2}
 ADD       EAX, EDX

end;



Страницы: 1 2 3 4 5 6 7 вся ветка

Форум: "Основная";
Текущий архив: 2004.10.24;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.77 MB
Время: 0.275 c
1-1097235292
Vir
2004-10-08 15:34
2004.10.24
Анализ кода


1-1097172263
dron-s
2004-10-07 22:04
2004.10.24
Изменение фокуса


14-1096609614
European
2004-10-01 09:46
2004.10.24
BreakPoints


8-1091110319
kblc
2004-07-29 18:11
2004.10.24
Как одновременно проиграть два файла?


1-1097139583
Andrey_
2004-10-07 12:59
2004.10.24
очистка image.picture





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский