Kopiowanie stringów - co szybsze

Kopiowanie stringów - co szybsze
JU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5046
0

No więc assembler mnie opanował.
Tym razem postanowiłem stworzyć funkcję do kopiowania łańcuchów. Skończyło się na tym, że stworzyłem dwie. Testowałem na łańuchach ponad 7 MB, jednak tickCount zwracał zawsze zero, więc nie wiem co o tym mysleć. Pytanie do mądrzejszych: która funkcja będzie szybsza na dużych i małych łańcuchach(pisane w Delphi):

Numero uno:

Kopiuj
function copy_str(str: string; startPos: integer; count: integer): string;
var
  s: string;
begin
  setLength(s, count);
  
asm
  mov ESI, str   {ustawiam sourceIndex}
  add ESI, startPos  {ustawiam pozycję, od której kopiować}
  mov EDI, s       {i dest index}

  mov ECX, count            {ustawiam ilość powtórzeń}

  rep movsb             {kopiuję bajt po bajcie}
end;

  result:=s;
end;

Numero duo:

Kopiuj
function copy_str(str: string; startPos: integer; count: integer): string;
var
  s: string;
begin
  setLength(s, count);
  
asm
  mov ESI, str              {ustawiam sourceIndex}
  add ESI, startPos       {ustawiam pozycję, od której kopiować}
  mov EDI, s                {gdzie kopiować}
  mov ECX, count         {ustawiam licznik - ilość pozostałych znaków}

  @check:
    cmp ECX, 4             {jeśli zostało więcej niż 3 znaki, kopiuj po 4 bajty}
    jae @b4

    cmp ECX, 2             {jeśli zostało więcej niż 1 znak, kopiuj po 2 bajty}
    jae @b2

    cmp ECX, 0             {jeśli już wszystko skopiowano, zakończ}
    je @end

  @b1:                        {kopiowanie ostatniego bajtu}
    movsb
    dec ECX;
    jmp @end

  @b2:                        {kopiowanie dwóch bajtów}
    movsw
    sub ECX, 2
    jmp @check

  @b4:                        {kopiowanie 4 bajtów}
    movsd
    sub ECX, 4
    jmp @check

  @end:
end;

  result:=s;
end;
Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
0

Spróbuj z QueryPerformanceCounter, powinien dawać lepszą dokładność czasu.

Jeśli chodzi o wydajność to możesz porównać ze standardowym memcpy i z funkcjami z asmlib.zip ze strony: http://agner.org/optimize/

Jeśli wyjdzie ci, że na procesorze X wersja A programu jest szybsza, to wcale nie oznacza to, iż na procesorze Y ta sama wersja też miałaby być szybsza. Przez to, że ten sam kod zachowuje się różnie na różnych architekturach są opcje optymalizacji kodu np w GCC - można ustawić dostrajanie kodu pod Core 2, Core i7, Bulldozera, Via Nano, Atoma, K8 itp itd

  • Rejestracja: dni
  • Ostatnio: dni
0

Spróbuj z QueryPerformanceCounter, powinien dawać lepszą dokładność czasu.

Czemu nie RDTSC? Toż to najprostsze do zrobienia i równie dokładne.

A co do funkcji: 2 jest (pewnie) szybsza, jakby ją ogarnąć to by była jeszcze szybsza. Powinieneś najpierw policzyć ile dwordów się zmieści a potem je skopiować i dopiero wtedy się zamartwiać ile ma koniec. poza tym powinno być to tak pomyślane, żeby skok wykonywał się rzadziej niż brak skoku.

  • Rejestracja: dni
  • Ostatnio: dni
0

Taki mały teścik sobie zrobiłem: http://pastebin.com/QaquMkNq
Mogę zaspoilerować że moja funkcja (123) wygrywa minimalnie z pierwszym algorytmem.

Oto moja funkcja:

Kopiuj
function copy_str_123(str: ansistring; startPos: integer; count: integer): ansistring;
var
  p:pointer;
  begin
    setLength(result, count);
    p:=@result[1];
  {$ASMMODE INTEL}
  asm
    mov ESI, str
    add ESI, startPos
    mov ECX,count
    mov EDI, p
    shr ECX,2

    rep movsd

    mov EBX,count
    and BL,03h

    test BL,BL
    jz @end

    cmp BL,2
    je @do2
    cmp BL,1
    je @do1

    @do3: movsw
    @do1: movsb
    jmp @end
    @do2: movsw

    @end:
  end;
  end;

I pewnie ten kod nie działa pod Delphi, ale pod FPC/Lazarusem powinien śmigać.

Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
0

QueryPerformanceCounter powinien być nieco bardziej miarodajny. W przypadku, gdy procesor ma tryb turbo i/ lub wiele poziomów spowolnienia/ przyspieszenia to mierzenie ilości taktów może dawać bardzo niedokładne wyniki.

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
0

http://wm.ite.pl/proj/sse2string/
kopiowania tam nie ma, ale niektóre funkcje też mogą się przydać.

xxx_xx_x
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 365
0

poczytaj o prefetch, tutaj masz gotowy przykład memcpy + prefetch + mmx
http://www.asmcommunity.net/board/index.php?topic=12804.0

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.