![]() |
Bitte Assembler-Routine verbessern
Hier habe ich eine Routine vom
![]() Hier die Routine:
Delphi-Quellcode:
Und hier meine gewünschte Funktionsdeklaration
function CharPos_JOH_SSE2_1_b(Ch : Char; const Str : AnsiString) : Integer;
asm test edx, edx jz @@NullString mov ecx, [edx-4] push ebx mov ebx, eax cmp ecx, 16 jl @@Small @@NotSmall: mov ah, al {Fill each Byte of XMM1 with AL} movd xmm1, eax pshuflw xmm1, xmm1, 0 pshufd xmm1, xmm1, 0 @@First16: movups xmm0, [edx] {Unaligned} pcmpeqb xmm0, xmm1 {Compare First 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@FoundStart {Exit on any Match} cmp ecx, 32 jl @@Medium {If Length(Str) < 32, Check Remainder} @@Align: sub ecx, 16 {Align Block Reads} push ecx mov eax, edx neg eax and eax, 15 add edx, ecx neg ecx add ecx, eax @@Loop: movaps xmm0, [edx+ecx] {Aligned} pcmpeqb xmm0, xmm1 {Compare Next 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@Found {Exit on any Match} add ecx, 16 jle @@Loop pop eax {Check Remaining Characters} add edx, 16 add eax, ecx {Count from Last Loop End Position} jmp dword ptr [@@JumpTable2-ecx*4] nop nop @@NullString: xor eax, eax {Result = 0} ret nop @@FoundStart: bsf eax, eax {Get Set Bit} pop ebx inc eax {Set Result} ret nop nop @@Found: pop edx bsf eax, eax {Get Set Bit} add edx, ecx pop ebx lea eax, [eax+edx+1] {Set Result} ret @@Medium: add edx, ecx {End of String} mov eax, 16 {Count from 16} jmp dword ptr [@@JumpTable1-64-ecx*4] nop nop @@Small: add edx, ecx {End of String} xor eax, eax {Count from 0} jmp dword ptr [@@JumpTable1-ecx*4] nop @@JumpTable1: dd @@NotFound, @@01, @@02, @@03, @@04, @@05, @@06, @@07 dd @@08, @@09, @@10, @@11, @@12, @@13, @@14, @@15, @@16 @@JumpTable2: dd @@16, @@15, @@14, @@13, @@12, @@11, @@10, @@09, @@08 dd @@07, @@06, @@05, @@04, @@03, @@02, @@01, @@NotFound @@16: add eax, 1 cmp bl, [edx-16] je @@Done @@15: add eax, 1 cmp bl, [edx-15] je @@Done @@14: add eax, 1 cmp bl, [edx-14] je @@Done @@13: add eax, 1 cmp bl, [edx-13] je @@Done @@12: add eax, 1 cmp bl, [edx-12] je @@Done @@11: add eax, 1 cmp bl, [edx-11] je @@Done @@10: add eax, 1 cmp bl, [edx-10] je @@Done @@09: add eax, 1 cmp bl, [edx-9] je @@Done @@08: add eax, 1 cmp bl, [edx-8] je @@Done @@07: add eax, 1 cmp bl, [edx-7] je @@Done @@06: add eax, 1 cmp bl, [edx-6] je @@Done @@05: add eax, 1 cmp bl, [edx-5] je @@Done @@04: add eax, 1 cmp bl, [edx-4] je @@Done @@03: add eax, 1 cmp bl, [edx-3] je @@Done @@02: add eax, 1 cmp bl, [edx-2] je @@Done @@01: add eax, 1 cmp bl, [edx-1] je @@Done @@NotFound: xor eax, eax pop ebx ret @@Done: pop ebx end;
Delphi-Quellcode:
Ich glaube, ich müsste nur zu der Adresse von 'Str' den Wert (aStart-1) hinzuaddieren und am Ende den Stack besser aufräumen, aber wie das geht weiss ich nicht.
function CharPos_JOH_SSE2_1_b(Ch : Char; const Str : AnsiString; aStart : Integer = 1) : Integer;
Na? Erweicht sich ein Asm-Guru, mir die Routine anzupassen? Frohes Fest an alle! |
Re: Bitte Assembler-Routine verbessern
Delphi-Quellcode:
Ich hab kein Delphi, um es zu testen.. Aber ich vermute, dass es so läuft. Was ich hier tue, entspricht weitgehend deiner Vermutung: am Anfang sagen wir einfach, dass der String aStart Zeichen kürzer ist als tatsächlich und setzen den Anfang des Strings (für die Funktion) auf das Zeichen bei aStart.
function CharPos_JOH_SSE2_1_b(Ch : Char; const Str : AnsiString; aStart : Integer = 1) : Integer;
asm test edx, edx jz @@NullString mov esi, ecx dec esi mov ecx, [edx-4] cmp esi, ecx jle @@Continue xor eax, eax ret @@Continue: add ecx, esi add edx, esi push ebx mov ebx, eax cmp ecx, 16 jl @@Small @@NotSmall: mov ah, al {Fill each Byte of XMM1 with AL} movd xmm1, eax pshuflw xmm1, xmm1, 0 pshufd xmm1, xmm1, 0 @@First16: movups xmm0, [edx] {Unaligned} pcmpeqb xmm0, xmm1 {Compare First 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@FoundStart {Exit on any Match} cmp ecx, 32 jl @@Medium {If Length(Str) < 32, Check Remainder} @@Align: sub ecx, 16 {Align Block Reads} push ecx mov eax, edx neg eax and eax, 15 add edx, ecx neg ecx add ecx, eax @@Loop: movaps xmm0, [edx+ecx] {Aligned} pcmpeqb xmm0, xmm1 {Compare Next 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@Found {Exit on any Match} add ecx, 16 jle @@Loop pop eax {Check Remaining Characters} add edx, 16 add eax, ecx {Count from Last Loop End Position} jmp dword ptr [@@JumpTable2-ecx*4] nop nop @@NullString: xor eax, eax {Result = 0} ret nop @@FoundStart: bsf eax, eax {Get Set Bit} pop ebx inc eax {Set Result} ret nop nop @@Found: pop edx bsf eax, eax {Get Set Bit} add edx, ecx pop ebx lea eax, [eax+edx+1] {Set Result} ret @@Medium: add edx, ecx {End of String} mov eax, 16 {Count from 16} jmp dword ptr [@@JumpTable1-64-ecx*4] nop nop @@Small: add edx, ecx {End of String} xor eax, eax {Count from 0} jmp dword ptr [@@JumpTable1-ecx*4] nop @@JumpTable1: dd @@NotFound, @@01, @@02, @@03, @@04, @@05, @@06, @@07 dd @@08, @@09, @@10, @@11, @@12, @@13, @@14, @@15, @@16 @@JumpTable2: dd @@16, @@15, @@14, @@13, @@12, @@11, @@10, @@09, @@08 dd @@07, @@06, @@05, @@04, @@03, @@02, @@01, @@NotFound @@16: add eax, 1 cmp bl, [edx-16] je @@Done @@15: add eax, 1 cmp bl, [edx-15] je @@Done @@14: add eax, 1 cmp bl, [edx-14] je @@Done @@13: add eax, 1 cmp bl, [edx-13] je @@Done @@12: add eax, 1 cmp bl, [edx-12] je @@Done @@11: add eax, 1 cmp bl, [edx-11] je @@Done @@10: add eax, 1 cmp bl, [edx-10] je @@Done @@09: add eax, 1 cmp bl, [edx-9] je @@Done @@08: add eax, 1 cmp bl, [edx-8] je @@Done @@07: add eax, 1 cmp bl, [edx-7] je @@Done @@06: add eax, 1 cmp bl, [edx-6] je @@Done @@05: add eax, 1 cmp bl, [edx-5] je @@Done @@04: add eax, 1 cmp bl, [edx-4] je @@Done @@03: add eax, 1 cmp bl, [edx-3] je @@Done @@02: add eax, 1 cmp bl, [edx-2] je @@Done @@01: add eax, 1 cmp bl, [edx-1] je @@Done @@NotFound: xor eax, eax pop ebx ret @@Done: pop ebx end; |
Re: Bitte Assembler-Routine verbessern
hi alzaimar,
die Funktion greift auf SSE2- und MMX-Register zu, die nicht bei jedem Prozessor verfügbar sind. Es könnte also durchaus sein, das die Funktion auf einem Athlon XP nette Fehlerchen wirft bzw. überhaupt nicht funktioniert. Aber frag doch mal John O'Harrow, ob er dir eine erweiterte Version bastelt/ zur Verfügung stellt. :mrgreen: |
Re: Bitte Assembler-Routine verbessern
Hi Dax, Hi bigg,
Erstmal Danke an Dich, Dax, für die Erweiterung. Das mit den Registern habe ich mir irgendwann mal so gedacht, zumal es bei den FastCode-Projekten eine Prozedure gibt, die anhand der CPU die korrekte Routine verwendet. So etwas in der Art sollte ich dann auch machen, um meine FastPos-Routine (Verbesserung des PosEx) allgemeingültig zu machen. Aber ich meine, das ich auf meinem Arbeits-PC (irgendso ein AMD 64) eine Version am Laufen habe ... Egal, ich check das mal. Danke auf jeden Fall! Und frohe Weihnacht an Alle. |
Re: Bitte Assembler-Routine verbessern
Die Athlon64 können auch SSE2, die "alten" 32er Athlon XP und darunter jedoch noch nicht. Nur SSE (ohne 2), aber immerhin können die schon MMX. Man kann eigentlich mittlerweile fast von MMX und SSE ausgehen, XPs sind aber denke ich noch genug im Einsatz um das zu bedenken. Alles weitere sind Sonderfälle meiner Meinung nach, zumindest im Desktopbereich.
|
Re: Bitte Assembler-Routine verbessern
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Dann sollte es hinter @@Continue heißen sub ecx,esi Oder hab ich da was falsch verstanden? Und mehr grundsätzlicher Natur : ESI sollte nicht verändert werden (oder vorher gepushed und vor dem RET wieder gepopt werden). @Alzaimar: Ich habe meine PosEx - Funktion inzwischen erweitert, sie kann jetzt vorwärts und rückwärts suchen, in beiden Fällen mit beliebigem AStart. Und : Wenn nur ein Zeichen gesucht wird, dann werden (sowohl für Vorwärtssuche wie auch Rückwärtssuche) Routinen benutzt, die auf dem Code von John O'Harrow basieren. |
Re: Bitte Assembler-Routine verbessern
Hi Amateurprofi. Du solltest für kurze Pattern die Gewinner der FastCode-Challenge 'PosEx' untersuchen. sie sind doch schneller als der Quicksearch. Meine Tests (Worstcase) haben das jedenfalls gezeigt.
Kannst Du mir freundlicherweise die korrigierte Version des von Dax bereits modifizierten Codes einstellen. Für Dich ist das ein Klacks, aber für mich eine Nummer zu groß.. Frohes Fest! |
Re: Bitte Assembler-Routine verbessern
@Profi: Du hast Recht! Ist mir gestern gar nicht aufgefallen, Danke :)
Wegen ESI: Ich hab den Code jetzt auf ESI-Erhalt erweitert, weiß auch nicht mehr, wo ich mir gemerkt hab, dass man ESI einfach ändern kann.. :gruebel:
Delphi-Quellcode:
function CharPos_JOH_SSE2_1_b(Ch : Char; const Str : AnsiString; aStart : Integer = 1) : Integer;
asm test edx, edx jz @@NullString push esi mov esi, ecx dec esi mov ecx, [edx-4] cmp esi, ecx jle @@Continue xor eax, eax pop esi ret @@Continue: sub ecx, esi add edx, esi push ebx mov ebx, eax cmp ecx, 16 jl @@Small @@NotSmall: mov ah, al {Fill each Byte of XMM1 with AL} movd xmm1, eax pshuflw xmm1, xmm1, 0 pshufd xmm1, xmm1, 0 @@First16: movups xmm0, [edx] {Unaligned} pcmpeqb xmm0, xmm1 {Compare First 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@FoundStart {Exit on any Match} cmp ecx, 32 jl @@Medium {If Length(Str) < 32, Check Remainder} @@Align: sub ecx, 16 {Align Block Reads} push ecx mov eax, edx neg eax and eax, 15 add edx, ecx neg ecx add ecx, eax @@Loop: movaps xmm0, [edx+ecx] {Aligned} pcmpeqb xmm0, xmm1 {Compare Next 16 Characters} pmovmskb eax, xmm0 test eax, eax jnz @@Found {Exit on any Match} add ecx, 16 jle @@Loop pop eax {Check Remaining Characters} add edx, 16 add eax, ecx {Count from Last Loop End Position} jmp dword ptr [@@JumpTable2-ecx*4] nop nop @@NullString: xor eax, eax {Result = 0} ret nop @@FoundStart: bsf eax, eax {Get Set Bit} pop ebx pop esi inc eax {Set Result} ret nop nop @@Found: pop edx bsf eax, eax {Get Set Bit} add edx, ecx pop ebx pop esi lea eax, [eax+edx+1] {Set Result} ret @@Medium: add edx, ecx {End of String} mov eax, 16 {Count from 16} jmp dword ptr [@@JumpTable1-64-ecx*4] nop nop @@Small: add edx, ecx {End of String} xor eax, eax {Count from 0} jmp dword ptr [@@JumpTable1-ecx*4] nop @@JumpTable1: dd @@NotFound, @@01, @@02, @@03, @@04, @@05, @@06, @@07 dd @@08, @@09, @@10, @@11, @@12, @@13, @@14, @@15, @@16 @@JumpTable2: dd @@16, @@15, @@14, @@13, @@12, @@11, @@10, @@09, @@08 dd @@07, @@06, @@05, @@04, @@03, @@02, @@01, @@NotFound @@16: add eax, 1 cmp bl, [edx-16] je @@Done @@15: add eax, 1 cmp bl, [edx-15] je @@Done @@14: add eax, 1 cmp bl, [edx-14] je @@Done @@13: add eax, 1 cmp bl, [edx-13] je @@Done @@12: add eax, 1 cmp bl, [edx-12] je @@Done @@11: add eax, 1 cmp bl, [edx-11] je @@Done @@10: add eax, 1 cmp bl, [edx-10] je @@Done @@09: add eax, 1 cmp bl, [edx-9] je @@Done @@08: add eax, 1 cmp bl, [edx-8] je @@Done @@07: add eax, 1 cmp bl, [edx-7] je @@Done @@06: add eax, 1 cmp bl, [edx-6] je @@Done @@05: add eax, 1 cmp bl, [edx-5] je @@Done @@04: add eax, 1 cmp bl, [edx-4] je @@Done @@03: add eax, 1 cmp bl, [edx-3] je @@Done @@02: add eax, 1 cmp bl, [edx-2] je @@Done @@01: add eax, 1 cmp bl, [edx-1] je @@Done @@NotFound: xor eax, eax pop ebx pop esi ret @@Done: pop ebx pop esi end; |
Re: Bitte Assembler-Routine verbessern
Hi,
Dank Euch beiden habe ich nun eine Version von PosEx, die wesentlich schneller ist als die Delphi-RTL Variante, und zwar in allen Lebenslagen. Dabei handelt es sich eigentlich um drei Routinen: 1. Wenn nach einem String der Länge 1 gesucht wird, dann wird die hier verbesserte CharPos-Variante aufgerufen 2. Wenn nach einem String der Länge 2,3 oder 4 gesucht wird, dann wird der Gewinner der PosEx-FastCode-Challenge aufgerufen 3. Wenn der zu durchsuchende Text kürzer als 1000 Zeichen ist, dann wird ebenfalls der Gewinner der PosEx-FastCode-Challenge aufgerufen. 4. In allen anderen Fällen wird die vom Amateurprofi optimierte QuickSearch-Variante aufgerufen. Ich eröffne einen neuen Thread und stelle 'meine' Routine, die ja in Wirklichkeit von John O'Hare, Amateurprofi, Dax und ein wenig von mir ist, vor. |
AW: Re: Bitte Assembler-Routine verbessern
Zitat:
könntest du bitte den oben erwähnten Thread hier verlinken? Ich bin an der endgültigen Version der Routine interessiert, habe den Thread aber leider nicht finden können. Danke :) /QStorm |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz