О производительности ассемблерных вставок...

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

О производительности ассемблерных вставок...

Сообщение beria » 03.10.2022 01:51:29

Задача : побайтовый обмен в массиве, квадратно-гнездовым способом.... Да, я знаю и использую avx, и да, он быстрее, но это не о нем...
Код: Выделить всё
procedure Swap1(Len: ptrUInt; P1, P2: Pointer); nostackframe; inline;
  assembler;
asm
         DEC     RCX
         @L:
         MOV     AL,[RDX+RCX]
         MOV     BL,[R8+RCX]
         MOV     [RDX+RCX],BL
         MOV     [R8+RCX],AL
         LOOP    @L

end ['RCX', 'RDX', 'R8', 'AX'];   

Код: Выделить всё
procedure Swap2 (Len: ptrUInt; P1, P2: Pointer); inline;
var
  j: byte;
  i: ptrUInt;
begin
  Dec(Len);
  for i := Len downto 0 do
  begin
    j := byte(P1^);
    byte(P1^) := byte(P2^);
    byte(P2^) := j;
    Inc(P1);
    Inc(P2);
  end;
end;


Результаты 5000000 прогонов на sizeof(shortstring) байт
1. 2218 мс
2. 907 мс

ИМХО по моему что-то не так с ассемблером в FPC... :o :o :o
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: О производительности ассемблерных вставок...

Сообщение iskander » 03.10.2022 09:55:00

Как-то кривовато это всё выглядит. Что случится, если в процедуры будет передана нулевая длина? Кроме того, цикл в ассемблерной процедуре кажется выполняет на одну итерацию меньше, чем требуется. Ну и, если правильно путаю, инструкция LOOP дороговатая, её лучше избегать.
С учётом сказанного:
Код: Выделить всё
procedure Swap1(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe; inline;
asm
  TEST  RCX, RCX
  JZ    @Done
@L:
  MOV   AL,[RDX+RCX]
  MOV   BL,[R8+RCX]
  MOV   [RDX+RCX],BL
  MOV   [R8+RCX],AL
  LOOP  @L
@Done:
end;

Код: Выделить всё
procedure Swap2(Len: ptrUInt; P1, P2: Pointer); inline;
var
  pb1: PByte absolute P1;
  pb2: PByte absolute P2;
  b: Byte;
  I: ptrUInt;
begin
  for I := 1 to Len do begin
    b := pb1^;
    pb1^ := pb2^;
    pb2^ := b;
    Inc(pb1);
    Inc(pb2);
  end;
end;

Код: Выделить всё
procedure Swap3(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe; inline;
asm
  test  rcx, rcx
  jz    @Done
@Loop:
  dec   rcx
  mov   al, [rdx+rcx]
  mov   bl, [r8+rcx]
  mov   [rdx+rcx], bl
  mov   [r8+rcx], al
  jnz   @Loop
@Done:
end;

Результат 5000000 прогонов на sizeof(shortstring):
Код: Выделить всё
Swap1: 1925
Swap2: 889
Swap3: 1029

А вообще-то, чтобы сравнивать сравнимое Swap2 должна выглядеть как-то так:
Код: Выделить всё
procedure Swap2(Len: ptrUInt; P1, P2: Pointer); inline;
var
  pb1: PByte absolute P1;
  pb2: PByte absolute P2;
  b: Byte;
  I: ptrUInt;
begin
  if Len = 0 then exit;
  for I := Len - 1 downto 0 do begin
    b := pb1[I];
    pb1[I] := pb2[I];
    pb2[I] := b;
  end;
end;

и тогда результат:
Код: Выделить всё
Swap1: 1905
Swap2: 1035
Swap3: 1029
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение Alex2013 » 03.10.2022 10:14:01

??? Народ не понял в чем прикол! :shock:
В начале топикастер как-то странно удивляется, что ассемблеровский код быстрее.
А потом iskander "исправляет" положение и обе асм-вставки работают медленнее кода на паскале.
Последний раз редактировалось Alex2013 03.10.2022 10:37:21, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: О производительности ассемблерных вставок...

Сообщение iskander » 03.10.2022 10:28:22

Alex2013 писал(а):??? Народ не понял в чем прикол!

Так обычно и бывает, если читать невнимательно.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение Alex2013 » 03.10.2022 10:35:57

О сори, не увидел этого . :oops:
Swap3: 1029
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: О производительности ассемблерных вставок...

Сообщение beria » 03.10.2022 11:47:20

Alex2013 писал(а):??? Народ не понял в чем прикол! :shock:
В начале топикастер как-то странно удивляется, что ассемблеровский код быстрее.

ассемблеровский код медленнее. В - значит "внимательность" )
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: О производительности ассемблерных вставок...

Сообщение Alex2013 » 03.10.2022 12:43:12

beria писал(а):ассемблеровский код медленнее. В - значит "внимательность" )

Уже заметил ...
Хотя вначале написано .
1. 2218 мс
2. 907 мс

Разумеется я соотнес 1. 2218 мс к Swap1, а 2. 907 мс Swap2.
Зы
Ладно в любом случае извиняюсь.
( Надо было самому проверить, а потом высказаться. Доберусь до лазаруса гляну ! :idea: )
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: О производительности ассемблерных вставок...

Сообщение iskander » 03.10.2022 17:59:51

beria писал(а):Результаты 5000000 прогонов на sizeof(shortstring) байт
1. 2218 мс
2. 907 мс

Alex2013 писал(а):Разумеется я соотнес 1. 2218 мс к Swap1, а 2. 907 мс Swap2.

Это круто.

Добавлено спустя 16 часов 29 минут 57 секунд:
Хех, совсем забыл, что согласно Windows x64 ABI, RBX не относится к изменяемым регистрам. Забавно, что оно при этом не падало.
В итоге Swap3 должна выглядеть как-то так:
Код: Выделить всё
procedure Swap3(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe;
asm
  test  rcx, rcx
  jz    @Done
@Loop:
  dec   rcx
  mov   al, [rdx+rcx]
  mov   r9b, [r8+rcx]
  mov   [rdx+rcx], r9b
  mov   [r8+rcx], al
  jnz   @Loop
@Done:
end;
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение beria » 04.10.2022 12:21:17

iskander писал(а):
beria писал(а):Результаты 5000000 прогонов на sizeof(shortstring) байт
то.

Добавлено спустя 16 часов 29 минут 57 секунд:
Хех, совсем забыл, что согласно Windows x64 ABI, RBX не относится к изменяемым регистрам. Забавно, что оно при этом не падало.
В итоге Swap3 должна выглядеть как-то так:


При том то вы действительно правы, но все равно не падает, где бы не встречалдся в коде ...
И при этом код ниже все равно быстрее на длину shortstring и цикл в 5000000
Причины конечно этого понял, но это не комплементарно к FPC, а кривая и недоделанная реализация там ассемблера, но с другой стороны компилятор в плане оптимизации чуть лучше, чем я думал ранее, правда до лучших образцов все равно не дотягивает.....
Код: Выделить всё
procedure Swap1(var P1, P2); inline;
var
  j: byte;
begin
  j := byte(P1);
  byte(P1) := byte(P2);
  byte(P2) := j;
end;


procedure Swap1(Len: PtrUint; var P1, P2); inline;
var
  i: ptrUInt;
  Pt1, Pt2: Pointer;
begin
  Pt1 := @P1;
  Pt2 := @P2;
  for i := 1 to Len do
  begin
    Swap1(Pt1^, Pt2^);
    Inc(Pt1);
    Inc(Pt2);
  end;
end;     
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: О производительности ассемблерных вставок...

Сообщение iskander » 04.10.2022 13:03:33

beria писал(а):И при этом код ниже все равно быстрее на длину shortstring и цикл в 5000000

Этот код, вероятно, правильнее сравнивать с чем-то таким:
Код: Выделить всё
procedure Swap2(Len: ptrUInt; P1, P2: Pointer); assembler; nostackframe;
asm
  test  rcx, rcx
  jz    @Done
@Loop:
  dec   rcx
  mov   al, [rdx]
  mov   r9b, [r8]
  mov   [rdx], r9b
  mov   [r8], al
  lea   rdx, [rdx+1]
  lea   r8, [r8+1]
  jnz   @Loop
@Done:
end;

На моей машине
Код: Выделить всё
Swap1: 905
Swap2: 873
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение beria » 04.10.2022 13:37:14

iskander писал(а):
beria писал(а):И при этом код ниже все равно быстрее на длину shortstring и цикл в 5000000


На моей машине
Код: Выделить всё
Swap1: 905
Swap2: 873



for i := 0 to 5000000 do Data.Swap1(sizeof(shortstring),sh1,sh2);875
for i := 0 to 5000000 do Data.Swap2(sizeof(shortstring),sh1,sh2);844

Ассемблер все таки победил! Ура. Мир вернулся в нормальное состояние... ))))))))
зы: кстати а вы не в курсе, вот таким способом "mov r9b, [r8]", можно побайтово получать содержимое 32-х байтовых AVX регистов?
Аватара пользователя
beria
постоялец
 
Сообщения: 130
Зарегистрирован: 29.09.2016 08:57:13

Re: О производительности ассемблерных вставок...

Сообщение iskander » 04.10.2022 14:43:54

Емнип в AVX для извлечения произвольных байтов из регистра была отдельная специально обученная инструкция VPEXTRB.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение Seenkao » 06.10.2022 14:09:01

Код: Выделить всё
procedure Swap1(Len: ptrUInt; P1, P2: Pointer); nostackframe; inline;
  assembler;
asm
    test rcx, rcx
    jz @done
    dec rcx
    cmp rcx, 8
    jz @L1
@L2:
    mov rax,[rdx+rcx]
    mov rbx,[r8+rcx]
    mov [rdx+rcx], rbx
    mov [r8+rcx], rax
    sub rcx, 8
    jnc @L2;  //  тут может быть ошибка
    add rcx, 8
@L1:
    mov al,[rdx+rcx]
    mov bl,[r8+rcx]
    mov [rdx+rcx],bl
    mov [r8+rcx],al
    dec rcx
    jnz @L1

@done:

end ['RCX', 'RDX', 'R8', 'AX'];

на коленке накидал.

Исправлено.
Последний раз редактировалось Seenkao 06.10.2022 20:08:34, всего редактировалось 1 раз.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

Re: О производительности ассемблерных вставок...

Сообщение iskander » 06.10.2022 16:34:41

Seenkao писал(а):procedure Swap1(Len: ptrUInt; P1, P2: Pointer); nostackframe; inline;
  assembler;
asm
    test rcx, rcx
    jz @done
    dec rcx
    cmp rcx, 4
    jz @L1
@L2:
    mov rax,[rdx+rcx]
    mov rbx,[r8+rcx]
    mov [rdx+rcx],bl
    mov [r8+rcx],al
    sub rcx, 4
    ja @L2;  //  тут может быть ошибка
    add rcx, 4
@L1:
    mov al,[rdx+rcx]
    mov bl,[r8+rcx]
    mov [rdx+rcx],bl
    mov [r8+rcx],al
    dec rcx
    jnz @L1

@done:

end ['RCX', 'RDX', 'R8', 'AX'];

на коленке накидал.

Такое впечатление, что прямо на заднице.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: О производительности ассемблерных вставок...

Сообщение Seenkao » 06.10.2022 20:10:51

iskander писал(а):Такое впечатление, что прямо на заднице.

если только на твоей.

Мне интересно, где ваша голова? Вместо предложения правок, хрень надо обязательно пронести.

Исправил недочёты в коде.

На самом деле надо ещё в начале делать проверку, чтоб данные не накладывались друг на друга.
Seenkao
энтузиаст
 
Сообщения: 502
Зарегистрирован: 01.04.2020 03:37:12

След.

Вернуться в Free Pascal Compiler

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

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

Рейтинг@Mail.ru