powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Микширование бит
104 сообщений из 104, показаны все 5 страниц
Микширование бит
    #40022657
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дано: 2 Word-а по 16 бит :)
Необходимо объединить их так, чтобы биты шли последовательно
Можно ли сделать это без многочисленных умножений или огромных заранее рассчитанных таблиц?

Пример:

0101010101010101 op 1100111000111100 = 0111001001110110111001110010
...
Рейтинг: 0 / 0
Микширование бит
    #40022663
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, в моём примере не так
Но важное уточнение

На практике не бывает, что оба n-ных бита равны 1
Может быть пригодится
...
Рейтинг: 0 / 0
Микширование бит
    #40022674
bk0010
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makewparam(lo,hi),
makelong(lo,hi),
LongRec(MyIntVariable).Lo := ..., LongRec(MyIntVariable).Hi := ...,
MyIntVariable:= Lo + Hi shl 16; ?
...
Рейтинг: 0 / 0
Микширование бит
    #40022678
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ошибся.
...
Рейтинг: 0 / 0
Микширование бит
    #40022681
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Ну у меня как-то так получилось в блокнотике:
Код: pascal
1.
2.
3.
4.
5.
6.
Result := 0; // DWORD;
for var i := 15 downto 0 do
begin
  Mask := 1 shl i; // Word
  Result := Result shl 1 or DWORD(WordA and Mask) shl 1 or DWORD(WordB and Mask);
end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022767
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Дано: 2 Word-а по 16 бит :)
Необходимо объединить их так, чтобы биты шли последовательно
Можно ли сделать это без многочисленных умножений или огромных заранее рассчитанных таблиц?

Пример:

0101010101010101 op 1100111000111100 = 0111001001110110111001110010


Ассемблер подойдет?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
function Mix( w1, w2 : word ) : dWord; assembler; register;
asm
     Push    ESI
     Push    EDI
     Push    EBX

     Xor     ESI,    ESI    // обнуляем временный результат
     Mov     EDI,    01h    // маска установки единичных битов w1 и w2

     Mov     ECX,    0Fh    // количество итераций
     Mov     EBX,    01h    // текущий сравниваемый бит для w1 и w2

@@10:
     Test    EAX,    EBX    // проверяем текущий бит для w1
     Jz      @@20

     Or      ESI,    EDI    // устанавливаем единичный бит w1

@@20:
     Shl     EDI,    01h    // сдвигаем текущий бит для w2
     Test    EDX,    EBX    // проверяем текущий бит для w2
     Jz      @@30

     Or      ESI,    EDI    // устанавливаем единичный бит w2

@@30:
     Shl     EDI,    01h    // сдвигаем текущий бит для w1
     Shl     EBX,    01h    // сдвигаем общий проверяемый бит
     Loop    @@10

     Mov     EAX,    ESI    // присваиваем временный результат

     Pop     EBX
     Pop     EDI
     Pop     ESI
end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022828
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я честно говоря думал есть способ обойтись парой умножений и битовыми операциями
В общем спасибо за участие!
...
Рейтинг: 0 / 0
Микширование бит
    #40022831
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

А зачем ассемблер?
Типа показать, что умеешь?
Или думаешь, так быстрее?
...
Рейтинг: 0 / 0
Микширование бит
    #40022844
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,
Такие вещи на ассемблере, как правило, быстрее.
В основном, за счет регистровой ручной оптимизации - нет обращений к стеку.
Ну, а показывать - не цель, чать не в детском садике )
...
Рейтинг: 0 / 0
Микширование бит
    #40022850
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov

Такие вещи на ассемблере, как правило, быстрее.
В основном, за счет регистровой ручной оптимизации - нет обращений к стеку.

AFAIK не всегда. Лично по моему опыту, компилятор значительно лучше оптимизирует последовательность инструкций (взаимовлияние), чем я.

Другое дело, что если использовать ASM, то тогда можно и MMX регистры использовать

Polesov

Mov ECX, 0Fh // количество итераций

Мне кажется, что задача должна решаться за log(32) операций, т.е. максимум 5 операций.
...
Рейтинг: 0 / 0
Микширование бит
    #40022852
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev,
согласен, надо смотреть в каждом конкретном случае.

Код: pascal
1.
  Mov ECX, 0Fh // количество итераций


Ну, это в лоб )
...
Рейтинг: 0 / 0
Микширование бит
    #40022853
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Давай зарубимся
Я напишу ту же функцию на паскале и она будет быстрее :)
С меня паскалевский вариант, с тебя бенчмарк )
...
Рейтинг: 0 / 0
Микширование бит
    #40022854
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev,

А как ты решишь за 5 операций?
Интересно
...
Рейтинг: 0 / 0
Микширование бит
    #40022855
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,
хорошо, выкладывай код.

Да уже с кем-то гонялись - в каких-то случаях asm проиграл почти в 1.5 раза.
...
Рейтинг: 0 / 0
Микширование бит
    #40022858
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Давай ты бенчмарк
Я часа через 2 подтянусь
...
Рейтинг: 0 / 0
Микширование бит
    #40022861
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Необходимо объединить их так, чтобы биты шли последовательно
Я правильно понял, что из abc и xyz надо получить axbycz ?

SOFT FOR YOU
огромных заранее рассчитанных таблиц?
А если не огромных? 128 Кбайт - это огромная?
...
Рейтинг: 0 / 0
Микширование бит
    #40022864
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoft,

Да

Да

:)
...
Рейтинг: 0 / 0
Микширование бит
    #40022868
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Polesov,
Давай ты бенчмарк

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
type
  TMixFunc = function ( w1, w2 : word ) : dWord;

function MixNop( w1, w2 : word ) : dWord; assembler; register;
asm
     Nop
end;

function MixAsm( w1, w2 : word ) : dWord; assembler; register;
asm
     Push    EBX

     Xor     EBX,    EBX    // обнуляем временный результат
     Mov     ECX,    01h    // устанавливаем маску единичного бита

@@10:
     Test    EAX,    01h    // проверяем бит для w1
     Jz      @@20

     Or      EBX,    ECX    // устанавливаем единичный бит w1

@@20:
     Shl     ECX,    01h    // сдвигаем маску единичного бита для w2
     Test    EDX,    01h    // проверяем бит для w2
     Jz      @@30

     Or      EBX,    ECX    // устанавливаем единичный бит w2

@@30:
     Shr     EAX,    01h    // сдвигаем w1 для проверки следующего бита
     Shr     EDX,    01h    // сдвигаем w2 для проверки следующего бита

     Shl     ECX,    01h    // сдвигаем маску единичного бита для w1
     Jecxz   @@40

     Jmp     @@10

@@40:
     Mov     EAX,    EBX

     Pop     EBX
end;

function MixPas( w1, w2 : word ) : dWord;
// реализация alekcvp
var
  i : integer;
  Mask : dWord;
begin
  Result := 0;
  for i := 15 downto 0 do
  begin
    Mask := 1 shl i;
    Result := Result shl 1 or DWORD(w1 and Mask) shl 1 or DWORD(w2 and Mask);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Nop : Int64;

  function Exec( Mix : TMixFunc ) : Int64;
  var
    t1, t2 : Int64;
    i : integer;
  begin
    QueryPerformanceCounter( t1 );
    for i := 1 to 1000000 do
      Mix( $1234, $4321 );
    QueryPerformanceCounter( t2 );
    Result := t2 - t1;
  end;

begin
  Nop := Exec( MixNop );
  Label1.Caption := 'Asm: ' + IntToStr( Exec( MixAsm ) - Nop );
  Label2.Caption := 'Pas: ' + IntToStr( Exec( MixPas ) - Nop );
end;



У меня получился выигрыш ~17%
...
Рейтинг: 0 / 0
Микширование бит
    #40022869
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вариант alekcvp мне нравиться больше.
...
Рейтинг: 0 / 0
Микширование бит
    #40022870
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Корректность работы проверяли?
...
Рейтинг: 0 / 0
Микширование бит
    #40022872
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
SOFT FOR YOU,

Ну у меня как-то так получилось в блокнотике:
Код: pascal
1.
2.
3.
4.
5.
6.
Result := 0; // DWORD;
for var i := 15 downto 0 do
begin
  Mask := 1 shl i; // Word
  Result := Result shl 1 or DWORD(WordA and Mask) shl 1 or DWORD(WordB and Mask);
end;



Почему "Result shl 1" ?
...
Рейтинг: 0 / 0
Микширование бит
    #40022873
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev
Корректность работы проверяли?

asm проверял
функцию alekcvp - нет (вместо нее SOFT FOR YOU обещался свою выложить)
...
Рейтинг: 0 / 0
Микширование бит
    #40022876
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Та-даааа )

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
unit Unit1;

{$O+}

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TMixFunc = function ( w1, w2 : word ) : dWord;

function MixNop( w1, w2 : word ) : dWord; assembler; register;
asm
     Nop
end;

function MixAsm( w1, w2 : word ) : dWord; assembler; register;
asm
     Push    EBX

     Xor     EBX,    EBX    // обнуляем временный результат
     Mov     ECX,    01h    // устанавливаем маску единичного бита

@@10:
     Test    EAX,    01h    // проверяем бит для w1
     Jz      @@20

     Or      EBX,    ECX    // устанавливаем единичный бит w1

@@20:
     Shl     ECX,    01h    // сдвигаем маску единичного бита для w2
     Test    EDX,    01h    // проверяем бит для w2
     Jz      @@30

     Or      EBX,    ECX    // устанавливаем единичный бит w2

@@30:
     Shr     EAX,    01h    // сдвигаем w1 для проверки следующего бита
     Shr     EDX,    01h    // сдвигаем w2 для проверки следующего бита

     Shl     ECX,    01h    // сдвигаем маску единичного бита для w1
     Jecxz   @@40

     Jmp     @@10

@@40:
     Mov     EAX,    EBX

     Pop     EBX
end;

function MixPas( w1, w2 : word ) : dWord;
// реализация alekcvp
var
  i : integer;
  Mask : dWord;
begin
  Result := 0;
  for i := 15 downto 0 do
  begin
    Mask := 1 shl i;
    Result := Result shl 1 or DWORD(w1 and Mask) shl 1 or DWORD(w2 and Mask);
  end;
end;

function MixPlane(w1, w2 : word ) : dWord;
// реализация SoftForYou
var
  X: Cardinal;
begin
  X := (Cardinal(w2) shl 16) + Cardinal(w1);

  Result := Cardinal(w1) and (1 shl 0);
  Inc(Result, (X and (1 shl 1)) shl 1);
  Inc(Result, (X and (1 shl 2)) shl 2);
  Inc(Result, (X and (1 shl 3)) shl 3);
  Inc(Result, (X and (1 shl 4)) shl 4);
  Inc(Result, (X and (1 shl 5)) shl 5);
  Inc(Result, (X and (1 shl 6)) shl 6);
  Inc(Result, (X and (1 shl 7)) shl 7);
  Inc(Result, (X and (1 shl 8)) shl 8);
  Inc(Result, (X and (1 shl 9)) shl 9);
  Inc(Result, (X and (1 shl 10)) shl 10);
  Inc(Result, (X and (1 shl 11)) shl 11);
  Inc(Result, (X and (1 shl 12)) shl 12);
  Inc(Result, (X and (1 shl 13)) shl 13);
  Inc(Result, (X and (1 shl 14)) shl 14);
  Inc(Result, (X and (1 shl 15)) shl 15);
  Inc(Result, (X and (1 shl (16 + 0))) shr (16 + 0 - 1));
  Inc(Result, (X and (1 shl (16 + 1))) shr (16 + 1 - 1));
  Inc(Result, (X and (1 shl (16 + 2))) shr (16 + 2 - 1));
  Inc(Result, (X and (1 shl (16 + 3))) shr (16 + 3 - 1));
  Inc(Result, (X and (1 shl (16 + 4))) shr (16 + 4 - 1));
  Inc(Result, (X and (1 shl (16 + 5))) shr (16 + 5 - 1));
  Inc(Result, (X and (1 shl (16 + 6))) shr (16 + 6 - 1));
  Inc(Result, (X and (1 shl (16 + 7))) shr (16 + 7 - 1));
  Inc(Result, (X and (1 shl (16 + 8))) shr (16 + 8 - 1));
  Inc(Result, (X and (1 shl (16 + 9))) shr (16 + 9 - 1));
  Inc(Result, (X and (1 shl (16 + 10))) shr (16 + 10 - 1));
  Inc(Result, (X and (1 shl (16 + 11))) shr (16 + 11 - 1));
  Inc(Result, (X and (1 shl (16 + 12))) shr (16 + 12 - 1));
  Inc(Result, (X and (1 shl (16 + 13))) shr (16 + 13 - 1));
  Inc(Result, (X and (1 shl (16 + 14))) shr (16 + 14 - 1));
  Inc(Result, (X and (1 shl (16 + 15))) shr (16 + 15 - 1));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Nop : Int64;

  function Exec( Mix : TMixFunc ) : Int64;
  var
    t1, t2 : Int64;
    i : integer;
  begin
    QueryPerformanceCounter( t1 );
    for i := 1 to 1000000 do
      Mix( $1234, $4321 );
    QueryPerformanceCounter( t2 );
    Result := t2 - t1;
  end;

begin
  Nop := Exec( MixNop );
  Label1.Caption := 'Asm: ' + IntToStr( Exec( MixAsm ) - Nop );
  Label2.Caption := 'Pas: ' + IntToStr( Exec( MixPas ) - Nop );
  Label3.Caption := 'Plane: ' + IntToStr( Exec( MixPlane ) - Nop );
end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022878
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUогромных заранее рассчитанных таблиц?

Табличка в 256 word (то бишь 512 байт) - огромна?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Микширование бит
    #40022879
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU

Пример:

0101010101010101 op 1100111000111100 = 0111001001110110111001110010

Похоже, у меня ошибка - в ТЗ младший бит результата = младший бит 2-го аргумента
У меня наоборот.
Вот подправленный вариант (на скорость не влияет):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
function MixAsm( w1, w2 : word ) : dWord; assembler; register;
asm
     Push    EBX

     Xor     EBX,    EBX    // обнуляем временный результат
     Mov     ECX,    01h    // устанавливаем маску единичного бита

@@10:
     Test    EDX,    01h    // проверяем бит для w2
     Jz      @@20

     Or      EBX,    ECX    // устанавливаем единичный бит w2

@@20:
     Shl     ECX,    01h    // сдвигаем маску единичного бита
     Test    EAX,    01h    // проверяем бит для w1
     Jz      @@30

     Or      EBX,    ECX    // устанавливаем единичный бит w1

@@30:
     Shl     ECX,    01h    // сдвигаем маску единичного бита
     Jecxz   @@40

     Shr     EAX,    01h    // сдвигаем w1 для проверки следующего бита
     Shr     EDX,    01h    // сдвигаем w2 для проверки следующего бита
     Jmp     @@10

@@40:
     Mov     EAX,    EBX

     Pop     EBX
end;


Результаты asm и pas совпадают.
...
Рейтинг: 0 / 0
Микширование бит
    #40022880
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov

Похоже, у меня ошибка - в ТЗ младший бит результата = младший бит 2-го аргумента


Ну это не критично
Я свой код не проверял )
...
Рейтинг: 0 / 0
Микширование бит
    #40022881
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Та-даааа )

Имя, сестра, имя ... )
Какие в итоге результаты?
...
Рейтинг: 0 / 0
Микширование бит
    #40022882
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

SOFT FOR YOUогромных заранее рассчитанных таблиц?

Табличка в 256 word (то бишь 512 байт) - огромна?


Ну через таблицы понятно как решить
Я чёт думал, что можно через умножения и сдвиги
А похоже что нельзя
Мож Шарахов придёт, интересный вариант накатает )
...
Рейтинг: 0 / 0
Микширование бит
    #40022883
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev

Почему "Result shl 1" ?

Потому что он "вдвигает" по 1му биту из WordA, а WordB остаётся на месте.
...
Рейтинг: 0 / 0
Микширование бит
    #40022884
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov,

Ну у кого как
У меня получилось в 2 раза быстрее, чем твой
...
Рейтинг: 0 / 0
Микширование бит
    #40022886
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Polesov,

Ну у кого как
У меня получилось в 2 раза быстрее, чем твой

Странно, у меня получилось, что твой вариант быстрее всего на ~2%, что и понятно - меньше переходов.
Видимо, зависит от модели процессора.
Если будет не влом, реализую твой алгоритм на asm и сравню ... )
...
Рейтинг: 0 / 0
Микширование бит
    #40022890
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
У меня получился выигрыш ~17%

Во-первых, надо увеличить количество итераций в 100 раз, а то у меня разброс времени выполнения от 170 до 240 при разных запусках.

Во-вторых, вот читерский вариант:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function MixPas2( w1, w2 : word ) : dWord;
const
  Mask: array [0..15] of Word =
    ($0001, $0002, $0004, $0008, $0010, $0020, $0040, $0080,
     $0100, $0200, $0400, $0800, $1000, $2000, $4000, $8000);
var
  i : integer;
begin
  Result := 0;
  for i := 15 downto 0 do
    Result := Result shl 1 or DWORD(w1 and Mask[i]) shl 1 or DWORD(w2 and Mask[i]);
end;



У меня на компе вот так:
Код: plaintext
1.
2.
3.
302845473 302845473 302845473
Asm: 14204237
Pas: 14497624
Tbl: 11670659

SOFT FOR YOU,

Результат твоего кода не совпадает с нашим.
...
Рейтинг: 0 / 0
Микширование бит
    #40022891
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Микширование бит
    #40022892
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Polesov
У меня получился выигрыш ~17%

Во-первых, надо увеличить количество итераций в 100 раз, а то у меня разброс времени выполнения от 170 до 240 при разных запусках.

Во-вторых, вот читерский вариант:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function MixPas2( w1, w2 : word ) : dWord;
const
  Mask: array [0..15] of Word =
    ($0001, $0002, $0004, $0008, $0010, $0020, $0040, $0080,
     $0100, $0200, $0400, $0800, $1000, $2000, $4000, $8000);
var
  i : integer;
begin
  Result := 0;
  for i := 15 downto 0 do
    Result := Result shl 1 or DWORD(w1 and Mask[i]) shl 1 or DWORD(w2 and Mask[i]);
end;



У меня на компе вот так:
Код: plaintext
1.
2.
3.
302845473 302845473 302845473
Asm: 14204237
Pas: 14497624
Tbl: 11670659

SOFT FOR YOU,

Результат твоего кода не совпадает с нашим.
А, понял, он тоже слова местами меняет.

Да, этот вариант быстрее
...
Рейтинг: 0 / 0
Микширование бит
    #40022893
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну мне кажется нет разницы, сначала идут биты w1 или w2
Ассемблер можно посмотреть дизассемблировав функцию (Ctrl+Alt+C в отладке)

Там кстати сделано в 3 регистра :)
...
Рейтинг: 0 / 0
Микширование бит
    #40022894
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Ты можешь ускорить свой вариант
Можно проинициализировать переменную Mask стартовым значением
Сделать repeat/until цикл, где на каждой итерации модифицируется Result и потом сдвигается Mask
При достижении Mask определенного значения - выходить из цикла
...
Рейтинг: 0 / 0
Микширование бит
    #40022899
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
alekcvp,

Ты можешь ускорить свой вариант
Можно проинициализировать переменную Mask стартовым значением
Сделать repeat/until цикл, где на каждой итерации модифицируется Result и потом сдвигается Mask
При достижении Mask определенного значения - выходить из цикла

Я уже забил маску в таблицу. Со сдвигом маски будет медленнее, я проверял.
Самый быстрый цикл - for , по крайней мере раньше был.
Хотел сделать свой ассеблерный вариант, но обломался.
На Z80 была команда сдвига через флаги (то ли ZF, то ли CF, не помню уже), был очень удивлён не обнаружив ничего похожего в x86...
...
Рейтинг: 0 / 0
Микширование бит
    #40022901
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Polesov,

Ну у кого как
У меня получилось в 2 раза быстрее, чем твой


Вот такая простыня оказалась самой быстрой )
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
function MixBig( w1, w2 : word ) : dWord; assembler; register;
asm
     Push    EBX

     Xor     EBX,    EBX

@@00:
     Test    EDX,    0001h
     Jz      @@01
     Or      EBX,    00000001h

@@01:
     Test    EAX,    0001h
     Jz      @@02
     Or      EBX,    00000002h

@@02:
     Test    EDX,    0002h
     Jz      @@03
     Or      EBX,    00000004h

@@03:
     Test    EAX,    0002h
     Jz      @@04
     Or      EBX,    00000008h

@@04:
     Test    EDX,    0004h
     Jz      @@05
     Or      EBX,    00000010h

@@05:
     Test    EAX,    0004h
     Jz      @@06
     Or      EBX,    00000020h

@@06:
     Test    EDX,    0008h
     Jz      @@07
     Or      EBX,    00000040h

@@07:
     Test    EAX,    0008h
     Jz      @@08
     Or      EBX,    00000080h

@@08:
     Test    EDX,    0010h
     Jz      @@09
     Or      EBX,    00000100h

@@09:
     Test    EAX,    0010h
     Jz      @@10
     Or      EBX,    00000200h

@@10:
     Test    EDX,    0020h
     Jz      @@11
     Or      EBX,    00000400h

@@11:
     Test    EAX,    0020h
     Jz      @@12
     Or      EBX,    00000800h

@@12:
     Test    EDX,    0040h
     Jz      @@13
     Or      EBX,    00001000h

@@13:
     Test    EAX,    0040h
     Jz      @@14
     Or      EBX,    00002000h

@@14:
     Test    EDX,    0080h
     Jz      @@15
     Or      EBX,    00004000h

@@15:
     Test    EAX,    0080h
     Jz      @@16
     Or      EBX,    00008000h

@@16:
     Test    EDX,    0100h
     Jz      @@17
     Or      EBX,    00010000h

@@17:
     Test    EAX,    0100h
     Jz      @@18
     Or      EBX,    00020000h

@@18:
     Test    EDX,    0200h
     Jz      @@19
     Or      EBX,    00040000h

@@19:
     Test    EAX,    0200h
     Jz      @@20
     Or      EBX,    00080000h

@@20:
     Test    EDX,    0400h
     Jz      @@21
     Or      EBX,    00100000h

@@21:
     Test    EAX,    0400h
     Jz      @@22
     Or      EBX,    00200000h

@@22:
     Test    EDX,    0800h
     Jz      @@23
     Or      EBX,    00400000h

@@23:
     Test    EAX,    0800h
     Jz      @@24
     Or      EBX,    00800000h

@@24:
     Test    EDX,    1000h
     Jz      @@25
     Or      EBX,    01000000h

@@25:
     Test    EAX,    1000h
     Jz      @@26
     Or      EBX,    02000000h

@@26:
     Test    EDX,    2000h
     Jz      @@27
     Or      EBX,    04000000h

@@27:
     Test    EAX,    2000h
     Jz      @@28
     Or      EBX,    08000000h

@@28:
     Test    EDX,    4000h
     Jz      @@29
     Or      EBX,    10000000h

@@29:
     Test    EAX,    4000h
     Jz      @@30
     Or      EBX,    20000000h

@@30:
     Test    EDX,    8000h
     Jz      @@31
     Or      EBX,    40000000h

@@31:
     Test    EAX,    8000h
     Jz      @@32
     Or      EBX,    80000000h

@@32:
     Mov     EAX,    EBX

     Pop     EBX
end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022902
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
SOFT FOR YOU,
Такие вещи на ассемблере, как правило, быстрее.
В основном, за счет регистровой ручной оптимизации - нет обращений к стеку.
сейчас обращение к стеку по скорости мало чем отличается от обращения к регистру
...
Рейтинг: 0 / 0
Микширование бит
    #40022905
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квейд
сейчас обращение к стеку по скорости мало чем отличается от обращения к регистру

Все же обращение к стеку хоть и немного, но медленнее обращения к регистру - где-то на 0.08%

Замерял на этом коде:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
procedure MovReg; assembler;
asm
     Mov    ECX,    100000000

@@10:
     Mov    EAX,    EBX
     Loop   @@10
end;

procedure MovMem; assembler;
asm
     Mov    ECX,    100000000

@@10:
     Mov    EAX,    dword ptr [EBP - 04h]
     Loop   @@10
end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022912
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov

Вот такая простыня оказалась самой быстрой )


А вот фиг:
Ассеблер для упоротых :)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
function MixAsm2( w1, w2 : word ) : dWord; assembler; register;
asm
  push    ebx
  push    ebp
  movzx   ebx, al
  shl     ebx, 16
  shl     eax, 8   // w1 - eax, ebx
  movzx   ecx, dl
  shl     ecx, 16
  shl     edx, 8   // w2 - edx, ecx
  mov     ebp, $8

@@loop:
  shr     ax, 1
  shr     bx, 1
  shr     eax, 1
  shr     ebx, 1
  shr     ecx, 1
  shr     edx, 1
  shr     cx, 1
  shr     dx, 1
  dec     ebp
  jnz     @@loop

  or      eax, edx
  shl     eax, 16
  or      ebx, ecx
  or      eax, ebx

  pop     ebp
  pop     ebx
end;


Код: plaintext
1.
BIG: 9331272
AA2: 8216673
...
Рейтинг: 0 / 0
Микширование бит
    #40022915
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выложите полный файл
А то сравниваете не понятно что с чем :)
...
Рейтинг: 0 / 0
Микширование бит
    #40022917
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
посмотрел список команд. увы, но проц нативно биты не почередует, ничего подходящего нет.
мне ассемблерный вариант с or mask нравится. наверно это лучшее, что можно сдлать
...
Рейтинг: 0 / 0
Микширование бит
    #40022919
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всё, быстрее уже не получается :)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
function MixAsm2( w1, w2 : word ) : dWord; assembler; register;
asm
  push    ebx
  movzx   ebx, al
  shl     eax, 8   // w1 - eax, ebx
  shl     ebx, 16
  movzx   ecx, dl
  shl     edx, 8   // w2 - edx, ecx
  shl     ecx, 16
  or      ebx, $7FFF

@@loop:
  shr     ecx, 1
  shr     edx, 1
  shr     cx, 1
  shr     dx, 1
  shr     ax, 1
  shr     bx, 1
  shr     eax, 1
  shr     ebx, 1
  jc      @@loop

  or      eax, edx
  shl     eax, 16
  or      ebx, ecx
  or      eax, ebx
  pop     ebx
end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022924
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

так немного быстрее
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function ShaMix(w1, w2: dword): dword;
begin;
  w1:=(w1 or w1 shl 8) and $00FF00FF;
  w2:=(w2 or w2 shl 8) and $00FF00FF;
  w1:=(w1 or w1 shl 4) and $0F0F0F0F;
  w2:=(w2 or w2 shl 4) and $0F0F0F0F;
  w1:=(w1 or w1 shl 2) and $33333333;
  w2:=(w2 or w2 shl 2) and $33333333;
  w1:=(w1 or w1 shl 1) and $55555555;
  w2:=(w2 or w2 shl 1) and $55555555;
  w1:=w1+w1;
  w1:=w1+w2;
  Result:=w1;
  end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022927
L1G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы что-то, ребята, затупили и с таблицами не попробовали.
Сибиряков правильно подсказал, они небольшие. Только их 2 нужно:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
var tbl0, tbl1: array[Byte] of Word;

procedure InitTables();
  var i, j, d, mask: byte;
begin
  for i:=0 to 255 do
  begin
    d := 0;
    for j := 0 to 7 do
    begin
      mask := 1 shl j;
      d := d or ((j and mask) shl j);
    end;
    tbl0[i] := d shl 1;
    tbl1[i] := d;
  end;
end;

function TableMix(w1, w2: word): dWord;
begin
  Result := ((tbl0[Hi(w1)] or tbl1[Hi(w2)]) shl 16) or tbl0[Lo(w1)] or tbl1[Lo(w2)];
end;
...
Рейтинг: 0 / 0
Микширование бит
    #40022928
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Только по условиям задачи тип параметров - word.

L1G,

Только время генерации таблиц тоже включай 🤣
...
Рейтинг: 0 / 0
Микширование бит
    #40022929
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Aleksandr Sharahov,

Только по условиям задачи тип параметров - word.


Значит, надо исправить условия.
...
Рейтинг: 0 / 0
Микширование бит
    #40022930
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но да, там всё равно уже бесполезно рыпаться 😁
...
Рейтинг: 0 / 0
Микширование бит
    #40022932
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Кстати, если её вручную на ассемблер перевести, то там прилично так в скорости прибавляется, чуть больше 20 процентов.
Всё-таки у новых дельфей с оптимизатором беда... 😒
...
Рейтинг: 0 / 0
Микширование бит
    #40022934
L1G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp, таблицы статикой в код ведь можно забить!
(btw, если их генерацию вставить перед миллионным циклом, как в тесте - он, как ни странно, ускоряется! за счет разогрева кэша, очевидно.)

Aleksandr Sharahov, результат операции не совпадает с таковым у других версий.

У меня тоже ошибочки вкрались в генерацию таблиц:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
procedure InitTables();
  var i, j, d, mask: word;
begin
  for i:=0 to 255 do
  begin
    d := 0;
    for j := 0 to 7 do
    begin
      mask := 1 shl j;
      d := d or ((i and mask) shl j);
    end;
    tbl0[i] := d shl 1;
    tbl1[i] := d;
  end;
end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022946
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Aleksandr Sharahov,

Кстати, если её вручную на ассемблер перевести, то там прилично так в скорости прибавляется, чуть больше 20 процентов.
Всё-таки у новых дельфей с оптимизатором беда... 😒


я пишу на D7 - у меня там ассемблер = паскаль )
...
Рейтинг: 0 / 0
Микширование бит
    #40022948
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
Aleksandr Sharahov
alekcvp
Aleksandr Sharahov,

Кстати, если её вручную на ассемблер перевести, то там прилично так в скорости прибавляется, чуть больше 20 процентов.
Всё-таки у новых дельфей с оптимизатором беда... 😒


я пишу на D7 - у меня там ассемблер = паскаль )


Тут принято всех, кто до сих пор на D7, ногами топтать !
...
Рейтинг: 0 / 0
Микширование бит
    #40022950
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G
Aleksandr Sharahov, результат операции не совпадает с таковым у других версий.


Значит, надо искать ошибку у других версий )
И разумеется, аргументы должны быть из диапазона 0..$FFFF
...
Рейтинг: 0 / 0
Микширование бит
    #40022953
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G

Aleksandr Sharahov, результат операции не совпадает с таковым у других версий.

Совпадает пока там параметры как DWORD объявлены, если поменять на Word то перестаёт совпадать.

Вот ассемблерный вариант того когда с правильными параметрами, у него всё совпадает и он даже ещё чуточку быстрее:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
function MixAsm3( w1, w2 : word ) : dWord; assembler; register;
asm
  push    ebx

  movzx   ebx, ax
  movzx   ecx, dx
  shl     eax, 8
  shl     edx, 8
  or      eax, ebx
  or      edx, ecx
  and     eax, $00FF00FF
  and     edx, $00FF00FF

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 4
  shl     ecx, 4
  or      eax, ebx
  or      edx, ecx
  and     eax, $0F0F0F0F
  and     edx, $0F0F0F0F

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 2
  shl     ecx, 2
  or      eax, ebx
  or      edx, ecx
  and     eax, $33333333
  and     edx, $33333333

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 1
  shl     ecx, 1
  or      eax, ebx
  or      edx, ecx
  and     eax, $55555555
  and     edx, $55555555

  shl     eax, 1
  or      eax, edx

  pop     ebx
end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022957
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
alekcvp,

так немного быстрее
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function ShaMix(w1, w2: dword): dword;
begin;
  w1:=(w1 or w1 shl 8) and $00FF00FF;
  w2:=(w2 or w2 shl 8) and $00FF00FF;
  w1:=(w1 or w1 shl 4) and $0F0F0F0F;
  w2:=(w2 or w2 shl 4) and $0F0F0F0F;
  w1:=(w1 or w1 shl 2) and $33333333;
  w2:=(w2 or w2 shl 2) and $33333333;
  w1:=(w1 or w1 shl 1) and $55555555;
  w2:=(w2 or w2 shl 1) and $55555555;
  w1:=w1+w1;
  w1:=w1+w2;
  Result:=w1;
  end;



Голова!
Расскажи, как мыслил, выводя такой подход
У меня не хватило соображалки )
...
Рейтинг: 0 / 0
Микширование бит
    #40022958
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp

Вот ассемблерный вариант того когда с правильными параметрами, у него всё совпадает и он даже ещё чуточку быстрее:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
function MixAsm3( w1, w2 : word ) : dWord; assembler; register;
asm
  push    ebx

  movzx   ebx, ax
  movzx   ecx, dx
  shl     eax, 8
  shl     edx, 8
  or      eax, ebx
  or      edx, ecx
  and     eax, $00FF00FF
  and     edx, $00FF00FF

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 4
  shl     ecx, 4
  or      eax, ebx
  or      edx, ecx
  and     eax, $0F0F0F0F
  and     edx, $0F0F0F0F

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 2
  shl     ecx, 2
  or      eax, ebx
  or      edx, ecx
  and     eax, $33333333
  and     edx, $33333333

  mov     ebx, eax
  mov     ecx, edx
  shl     ebx, 1
  shl     ecx, 1
  or      eax, ebx
  or      edx, ecx
  and     eax, $55555555
  and     edx, $55555555

  shl     eax, 1
  or      eax, edx

  pop     ebx
end;



Сравни это с результатом компилятора D7, у него код быстрее )

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
function ShaAsm(w1, w2: dword): dword;
asm
  mov ecx, eax
  shl ecx, 8
  or  eax, ecx
  and eax, $00FF00FF
  mov ecx, edx
  shl ecx, 8
  or  edx, ecx
  and edx, $00FF00FF

  mov ecx, eax
  shl ecx, 4
  or  eax, ecx
  and eax, $0F0F0F0F
  mov ecx, edx
  shl ecx, 4
  or  edx, ecx
  and edx, $0F0F0F0F

  mov ecx, eax
  shl ecx, 2
  or  eax, ecx
  and eax, $33333333
  mov ecx, edx
  shl ecx, 2
  or  edx, ecx
  and edx, $33333333

  mov ecx, eax
  shl ecx, 1
  or  eax, ecx
  and eax, $55555555
  mov ecx, edx
  shl ecx, 1
  or  edx, ecx
  and edx, $55555555

  add eax, eax
  add eax, edx
  end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022959
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G
Вы что-то, ребята, затупили и с таблицами не попробовали.
Сибиряков правильно подсказал, они небольшие. Только их 2 нужно:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
var tbl0, tbl1: array[Byte] of Word;

procedure InitTables();
  var i, j, d, mask: byte;
begin
  for i:=0 to 255 do
  begin
    d := 0;
    for j := 0 to 7 do
    begin
      mask := 1 shl j;
      d := d or ((j and mask) shl j);
    end;
    tbl0[i] := d shl 1;
    tbl1[i] := d;
  end;
end;

function TableMix(w1, w2: word): dWord;
begin
  Result := ((tbl0[Hi(w1)] or tbl1[Hi(w2)]) shl 16) or tbl0[Lo(w1)] or tbl1[Lo(w2)];
end;



Просто через таблицы понятно как решать :)
...
Рейтинг: 0 / 0
Микширование бит
    #40022960
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
Сравни это с результатом компилятора D7, у него код быстрее )

Во-первых, сделай входящие параметры Word, чтобы сравнение было в одинаковых условиях.

Во-вторых, да у новых дельфей с оптимизатором беда, согласен.

В-третьих, тут скорее от процессора зависит, потому что перестановка местами команд в теле и замена add на shl/or у меня давала прирост в производительности. Возможно это как-то влияет на кэш/распараллелливание инструкций.
...
Рейтинг: 0 / 0
Микширование бит
    #40022963
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp
Aleksandr Sharahov
Сравни это с результатом компилятора D7, у него код быстрее )

Во-первых, сделай входящие параметры Word, чтобы сравнение было в одинаковых условиях.


В ассемблерном варианте (тот который ShaAsm) можешь нарисовать любые параметры, код будет работать.
Я смотрю на вещи ширше )

alekcvp

Во-вторых, да у новых дельфей с оптимизатором беда, согласен.


Речь не о новых дельфи.
А о том, что компилятор D7 часто порождает код лучше человеков.
...
Рейтинг: 0 / 0
Микширование бит
    #40022964
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Оптимизация новых Delphi не хуже, чем Delphi 7
Скорее у тебя не включен флаг оптимизации

P.S. Перевести Word в Cardinal - плёвое дело
...
Рейтинг: 0 / 0
Микширование бит
    #40022967
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Оптимизация новых Delphi не хуже, чем Delphi 7
Скорее у тебя не включен флаг оптимизации

1. Хуже, уже неоднократно проверялось.
2. Он по-умолчанию включён для Release.
...
Рейтинг: 0 / 0
Микширование бит
    #40022968
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

На операциях с управляемыми типами - да
Там дополнительные операции вставлены
Но здесь нет управляемых типов
...
Рейтинг: 0 / 0
Микширование бит
    #40022969
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
alekcvp,

На операциях с управляемыми типами - да
Там дополнительные операции вставлены
Но здесь нет управляемых типов


Попробуй откомпилировать 22239616
и сравнить результат с 22239671
Это подлинная выдача из D7
...
Рейтинг: 0 / 0
Микширование бит
    #40022975
L1G
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov, извиняюсь, с входными параметрами dword - всё ОК

кстати, идея dword-параметров - отличная! табличный метод резко вырывается вперед (в 2 раза быстрее стал!)
Код: pascal
1.
2.
3.
4.
function TableMix1(w1, w2: dword): dword;
begin
  Result := (((tbl1[Hi(w1)] shl 1) or tbl1[Hi(w2)]) shl 16) or (tbl1[Lo(w1)] shl 1) or tbl1[Lo(w2)];
end;


и с одной таблицей даже чуть быстрее, чем с двумя.

SOFT FOR YOU, интересно ведь скорости-то сравнить.
если "наивный" (легко понятный) код еще и быстрее оказывается - зачем что-то еще?

И т.к. Александр не "рассказал, как мыслил", могу предположить:
- 16 бит нам нужно сместить на разные смещения, от 0 до 15
- смещать биты можно и по нескольку сразу, но на одинаковый оффсет
- если оффсеты будут степенями двойки - можно уменьшить количество нужных смещений логарифмически
- начинать нужно с больших оффсетов, т.е. сначала весь старший байт - влево на 8
- дальше - дело техники.
...
Рейтинг: 0 / 0
Микширование бит
    #40022986
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov

Сравни это с результатом компилятора D7, у него код быстрее )

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
function ShaAsm(w1, w2: dword): dword;
asm
  mov ecx, eax
  shl ecx, 8
  or  eax, ecx
  and eax, $00FF00FF
  mov ecx, edx
  shl ecx, 8
  or  edx, ecx
  and edx, $00FF00FF

  mov ecx, eax
  shl ecx, 4
  or  eax, ecx
  and eax, $0F0F0F0F
  mov ecx, edx
  shl ecx, 4
  or  edx, ecx
  and edx, $0F0F0F0F

  mov ecx, eax
  shl ecx, 2
  or  eax, ecx
  and eax, $33333333
  mov ecx, edx
  shl ecx, 2
  or  edx, ecx
  and edx, $33333333

  mov ecx, eax
  shl ecx, 1
  or  eax, ecx
  and eax, $55555555
  mov ecx, edx
  shl ecx, 1
  or  edx, ecx
  and edx, $55555555

  add eax, eax
  add eax, edx
  end;



Добавляем первой строкой весьма безобидную ни на что не влияющую операцию
Код: pascal
1.
  xor  ecx, ecx


и получаем замедление где-то в 1.5 раза
Уш-да-уш... Оптимизация asm - дело тонкое ...
...
Рейтинг: 0 / 0
Микширование бит
    #40022988
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov

Добавляем первой строкой весьма безобидную ни на что не влияющую операцию
Код: pascal
1.
  xor  ecx, ecx


и получаем замедление где-то в 1.5 раза
Уш-да-уш... Оптимизация asm - дело тонкое ...


Ты сейчас с компилятором разговариваешь? ))
Это его выхлоп.
...
Рейтинг: 0 / 0
Микширование бит
    #40022989
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G
могу предположить:
- 16 бит нам нужно сместить на разные смещения, от 0 до 15
- смещать биты можно и по нескольку сразу, но на одинаковый оффсет
- если оффсеты будут степенями двойки - можно уменьшить количество нужных смещений логарифмически
- начинать нужно с больших оффсетов, т.е. сначала весь старший байт - влево на 8
- дальше - дело техники.


Да, так и думал. Это стандартный прием. Но на таблицах, конечно быстрее будет.

версия на таблицах
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
var
  tbl: array[0..255] of dword;

procedure FillTable;
var
  i, j, k, m: integer;
begin;
  for i:=0 to 255 do begin;
    j:=0; m:=1;
    repeat;
      k:=i and m;
      j:=j + k*k;
      m:=m+m;
      until m>=256;
    tbl[i]:=j;
    end;
  end;

function ShaTableAsm(w1, w2: dword): dword;
asm
  movzx ecx, dh
  xor ecx, eax
  movzx eax, al
  xor ecx, eax
  mov eax, [eax*4+tbl]
  add eax, eax
  movzx edx, dl
  or eax, [edx*4+tbl]
  movzx edx, ch
  mov edx, [edx*4+tbl]
  add edx, edx
  movzx ecx, cl
  or edx, [ecx*4+tbl]
  shl edx, 16
  add eax, edx
  end;

...
Рейтинг: 0 / 0
Микширование бит
    #40022991
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
Polesov

Добавляем первой строкой весьма безобидную ни на что не влияющую операцию
Код: pascal
1.
  xor  ecx, ecx


и получаем замедление где-то в 1.5 раза
Уш-да-уш... Оптимизация asm - дело тонкое ...


Ты сейчас с компилятором разговариваешь? ))
Это его выхлоп.

Да нет - речь о том, что даже, на первый взгляд, незначительное изменение кода может существенно повлиять на скорость выполнения.
...
Рейтинг: 0 / 0
Микширование бит
    #40022994
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G

SOFT FOR YOU, интересно ведь скорости-то сравнить.
если "наивный" (легко понятный) код еще и быстрее оказывается - зачем что-то еще?


Я тут экспериментирую с SIMD
По сути появится возможность анализировать 16 символов за раз
Там классная возможность в том, что проведя ряд манипуляций, ты получаешь маску из 16 бит, где ты видишь, символ удовлетворяет твоему условию или нет

Например, самое важное условие - является ли символ ASCII (т.е. <= $7f)
Но по факту возникает необходимость анализировать сразу несколько условий
Например, тебе так же нужно по-особому реагировать на символы перевода каретки или пробельные символы. В кодировке FlexString (Flex Unicode) ключевое значение имеет символ $ff

Получается ты считал 16 символов из памяти. Проанализировал их, получил маску (2 маски по 16 бит)
А потом постепенно вычитываешь эти символы из SIMD-регистра и обрабатываешь согласно имеющейся маске

Так вот я подумал было бы классно объединить 2 маски в одну и анализировать каждый символ как последовательность 2 бит (первая маска плюс вторая)
Я думал можно сделать это за пару тактов. Каким-то простым способом. Таблицы уже не резонно. Остальные методы ещё хуже. Придётся усложнить анализ маски - первые 16 бит будут в младшем слове, а вторые в старшем. В данном случае мы просто разминаем мозги на тему как и что можно реализовать. Да, кстати, можно провести сравнительное тестирование. Мне кажется вариант Шарахова будет примерно таким же :)
...
Рейтинг: 0 / 0
Микширование бит
    #40022995
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
alekcvp,

так немного быстрее
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
function ShaMix(w1, w2: dword): dword;
begin;
  w1:=(w1 or w1 shl 8) and $00FF00FF;
  w2:=(w2 or w2 shl 8) and $00FF00FF;
  w1:=(w1 or w1 shl 4) and $0F0F0F0F;
  w2:=(w2 or w2 shl 4) and $0F0F0F0F;
  w1:=(w1 or w1 shl 2) and $33333333;
  w2:=(w2 or w2 shl 2) and $33333333;
  w1:=(w1 or w1 shl 1) and $55555555;
  w2:=(w2 or w2 shl 1) and $55555555;
  w1:=w1+w1;
  w1:=w1+w2;
  Result:=w1;
end;



Rio - почти идентично. Пара сдвигов заменены на инкремент

P.S. ты кстати не ответил на вопрос :)
22239670
...
Рейтинг: 0 / 0
Микширование бит
    #40022997
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Ответил 22239731
Думал, что это более-менее очевидно. Прокрути алгоритм по шагам.
После первого сдвига остаются пары одинаковых сдвигов, и т.д.
...
Рейтинг: 0 / 0
Микширование бит
    #40022999
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
L1G
- 16 бит нам нужно сместить на разные смещения, от 0 до 15

От 0 до 17 )

Polesov

Добавляем первой строкой весьма безобидную ни на что не влияющую операцию
Код: pascal
1.
  xor  ecx, ecx


и получаем замедление где-то в 1.5 раза
Уш-да-уш... Оптимизация asm - дело тонкое ...


Выложи текущий вариант модуля
Чтобы мы тоже погоняли и сравнили
...
Рейтинг: 0 / 0
Микширование бит
    #40023000
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

у тебя какой-то странный листинг.

Возьми мои ассемблерные 22239671 и 22239731 .
...
Рейтинг: 0 / 0
Микширование бит
    #40023001
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov
SOFT FOR YOU,

у тебя какой-то странный листинг.

Возьми мои ассемблерные 22239671 и 22239731 .


Справа и есть твой листинг (2 первые строки идентичны, на скриншот не поместились)
Слева Rio
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
    mov ecx,eax
    shl ecx,$08
    or eax,ecx
    and eax,$00ff00ff
    mov ecx,edx
    shl ecx,$08
    or edx,ecx
    and edx,$00ff00ff
    mov ecx,eax
    shl ecx,$04
    or eax,ecx
    and eax,$0f0f0f0f
    mov ecx,edx
    shl ecx,$04
    or edx,ecx
    and edx,$0f0f0f0f
    mov ecx,eax
    add ecx,ecx
    add ecx,ecx
    or eax,ecx
    and eax,$33333333
    mov ecx,edx
    add ecx,ecx
    add ecx,ecx
    or edx,ecx
    and edx,$33333333
    mov ecx,eax
    add ecx,ecx
    or eax,ecx
    and eax,$55555555
    mov ecx,edx
    add ecx,ecx
    or edx,ecx
    and edx,$55555555
    add eax,eax
    add eax,edx




Насчёт стандартного подхода
А можно это как-то где-то почитать?
Желательно на русском
...
Рейтинг: 0 / 0
Микширование бит
    #40023003
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

гугли bit twiddling hacks
...
Рейтинг: 0 / 0
Микширование бит
    #40023005
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

👍
...
Рейтинг: 0 / 0
Микширование бит
    #40023006
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU

Polesov

Добавляем первой строкой весьма безобидную ни на что не влияющую операцию
Код: pascal
1.
  xor  ecx, ecx


и получаем замедление где-то в 1.5 раза
Уш-да-уш... Оптимизация asm - дело тонкое ...


Выложи текущий вариант модуля
Чтобы мы тоже погоняли и сравнили

Да чо там выкладывать )
Берем код от Aleksandr Sharahov, сгенеренный D7 (только тип входных параметров меняем на word)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
function ShaAsm(w1, w2: word): dword;
asm
  mov ecx, eax
  shl ecx, 8
  or  eax, ecx
  and eax, $00FF00FF
  mov ecx, edx
  shl ecx, 8
  or  edx, ecx
  and edx, $00FF00FF

  mov ecx, eax
  shl ecx, 4
  or  eax, ecx
  and eax, $0F0F0F0F
  mov ecx, edx
  shl ecx, 4
  or  edx, ecx
  and edx, $0F0F0F0F

  mov ecx, eax
  shl ecx, 2
  or  eax, ecx
  and eax, $33333333
  mov ecx, edx
  shl ecx, 2
  or  edx, ecx
  and edx, $33333333

  mov ecx, eax
  shl ecx, 1
  or  eax, ecx
  and eax, $55555555
  mov ecx, edx
  shl ecx, 1
  or  edx, ecx
  and edx, $55555555

  add eax, eax
  add eax, edx
end;


Замеряем скорость.
Добавляем первой строчкой
Код: pascal
1.
  Xor   ECX,   ECX


и сравниваем с тем, что было до ...
...
Рейтинг: 0 / 0
Микширование бит
    #40023046
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, и до кучи - наверное, самый компактный вариант:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
function MixRcr( w1, w2 : word ) : dWord; assembler; register;
asm
     Push   EBX

     Mov    EBX,    EAX    // освобождаем регистр результата
     Mov    ECX,    0Fh    // счетчик цикла

@@10:
     Ror    EDX,    01h    // устанавливаем CF в зависимости от текущего бита w2
     Rcr    EAX,    01h    // задвигаем слева в результат из CF текущий бит w2

     Ror    EBX,    01h    // устанавливаем CF в зависимости от текущего бита w1
     Rcr    EAX,    01h    // задвигаем слева в результат из CF текущий бит w1

//     Loop   @@10 - использование loop для управления циклом увеличивает время чуть более, чем в 2 раза
     Dec    ECX            // проверка счетчика цикла
     Jnz    @@10

     Pop    EBX
end;


И, кстати, не самый медленный )
...
Рейтинг: 0 / 0
Микширование бит
    #40023081
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Хотел через умножения?
Распишитесь в получении.

Не спрашивай, как )
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
function ShaMixCool(u, v: dword): dword;
var
  x, y: dword;
begin;
  x:=u and $2492; x:=x*x and $04104104;
  y:=u and $4924; x:=y*y and $10410410 + x;
  u:=u and $9249; x:=u*u and $41041041 + x;

  y:=v and $2492; y:=y*y and $04104104;
  u:=v and $4924; y:=u*u and $10410410 + y;
  v:=v and $9249; y:=v*v and $41041041 + y;

  x:=x+x;
  x:=x+y;
  Result:=x;
  end;
...
Рейтинг: 0 / 0
Микширование бит
    #40023087
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU
Я тут экспериментирую с SIMD
По сути появится возможность анализировать 16 символов за раз
Там классная возможность в том, что проведя ряд манипуляций, ты получаешь маску из 16 бит, где ты видишь, символ удовлетворяет твоему условию или нет
<..>
Получается ты считал 16 символов из памяти. Проанализировал их, получил маску (2 маски по 16 бит)
А потом постепенно вычитываешь эти символы из SIMD-регистра и обрабатываешь согласно имеющейся маске
Если ты в конечном итоге будешь "вычитывать символы" по одному, то ускорение от SIMD возможно только на пропуске пустого места - когда ни один бит в маске не установлен, можно сразу пропустить эти символы. Если таких итераций много, то ОК.
Если нет - нужно думать, как делать обработку (возможно, не всю, а некоторые из этапов) тру-симдовским методом - считать обе ветки условия и микшировать их по маске, без посимвольного разбора и условных jmp-ов.
...
Рейтинг: 0 / 0
Микширование бит
    #40023090
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

Так этот вариант ещё медленнее, чем через сдвиги )
Но спрашивать не буду
Видимо всё равно не пойму )
...
Рейтинг: 0 / 0
Микширование бит
    #40023093
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky,

Зависит от алгоритма
Наибольшей производительности получается достичь если все символы ASCII
Условно говоря при конвертации Ansi в Utf8 - тупо кидаешь все символы и всё
Но возникает вопрос, как быть если встречен не целевой символ
Можно прочитать и обработать его стандартным способом
А можно прикинуть, что в SIMD регистр уже прочитаны данные, а в маске лежит инфа, где что лежит
Получается я SIMD регистр могу использовать не просто, чтобы анализировать, где какие символы идут
Но и как оперативное хранилище прочитанных данных!
...
Рейтинг: 0 / 0
Микширование бит
    #40023094
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Aleksandr Sharahov,

Так этот вариант ещё медленнее, чем через сдвиги )
Но спрашивать не буду
Видимо всё равно не пойму )


Да, он примерно на 25% медленнее, но зато прикольный:
использованные в нем константы - единственные,
которые позволяют независимо возводить биты числа в квадрат.
Других троек констант с такими свойствами нет.
...
Рейтинг: 0 / 0
Микширование бит
    #40023097
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU
Aleksandr Sharahov,
Так этот вариант ещё медленнее, чем через сдвиги )


Кстати, асм-версия на умножениях обгоняет асм-версию на сдвигах примерно на 10%:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
function ShaMixCoolAsm(u, v: dword): dword;
asm
  push ebx
  mov ebx, eax
  and ebx, $2492
  imul ebx, ebx
  and ebx, $04104104
  mov ecx, eax
  and ecx, $4924
  imul ecx, ecx
  and ecx, $10410410
  add ecx, ebx
  and eax, $9249
  imul eax, eax
  and eax, $41041041
  add eax, ecx

  mov ebx, edx
  and ebx, $2492
  imul ebx, ebx
  and ebx, $04104104
  mov ecx, edx
  and ecx, $4924
  imul ecx, ecx
  and ecx, $10410410
  add ecx, ebx
  and edx, $9249
  imul edx, edx
  and edx, $41041041
  add edx, ecx

  lea eax,[edx+eax*2]
  pop ebx
  end;
...
Рейтинг: 0 / 0
Микширование бит
    #40023098
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
удалил дубликат
...
Рейтинг: 0 / 0
Микширование бит
    #40023100
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU
Sapersky,
Условно говоря при конвертации Ansi в Utf8 - тупо кидаешь все символы и всё
Но возникает вопрос, как быть если встречен не целевой символ
А, ну если "левые" символы изредка встречаются, тогда может и будет толк.
SOFT FOR YOU
А можно прикинуть, что в SIMD регистр уже прочитаны данные, а в маске лежит инфа, где что лежит
Получается я SIMD регистр могу использовать не просто, чтобы анализировать, где какие символы идут
Но и как оперативное хранилище прочитанных данных!
Не факт, что разбор маски - это так уж быстро.
Если использовать bsr, то нужно очищать каждый найденный бит. Если просто всё перебирать, то это shr/and/условие для каждого бита.
Я кстати возился со строками и SIMD год назад:
https://www.sql.ru/forum/1319647-a/poisk-v-fayle-s-ispolzovaniem-mmf
хотя там разбор маски точно неоптимален, перебор всех бит на Паскале.
...
Рейтинг: 0 / 0
Микширование бит
    #40023122
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Описание логики работы алгоритма на умножениях
22239874 и 22239895 .

Как и в алгоритме на сдвигах мы вычисляем для переданных
параметров (u,v) 2 промежуточных результата t(u) и t(v),
а затем на их основе получаем окончательный результат
r(u,v)=2*t(u)+t(v).

Отличие от алгоритма на сдвигах состоит в том,
какими операторами t мы раздвигаем биты каждого параметра.

Очевидно, что t(0)=0.

Понятно, что если параметр содержит ровно 1 ненулевой бит
в i-той позиции, то t(2^i)=2^(2*i)=(2^i)*(2^i), или t(x)=x*x.
Т.е. и в этом случае достаточно возвести параметр в квадрат.

При возведении в квадрат параметра, содержащего
2 ненулевых бита, в соответствии биномом Ньютона,
мы получим (x+y)*(x+y)=x*x+y*y+2*x*y.
А правильный результат t(x+y)=x*x+y*y.
Т.е. в этом случае мы получили погрешность в виде
удвоенного произведения ненулевых битов.

Если параметр будет содержать большее количество
ненулевых битов, то при возведении в квадрат мы
будем получать погрешность для каждой пары битов.

Избавиться от погрешности наложением битовой маски
на результат возведения в квадрат невозможно,
т.к. позиции битов погрешности могут совпадать
с позициями битов результата.

Однако, если произвольно выбрать некоторое
множество разрешенных позиций битов параметра,
то для него мы можем указать
множество разрешенных позиций битов результата.

Далее мы будем рассматривать только "хорошие"
множества разрешенных позиций битов параметра,
для которых биты погрешности не попадают
в множество разрешенных позиций битов результата.

Несмотря на то что хороших множеств довольно много,
их мощность невелика. Самое большое хорошее множество
состоит из 6 битовых позиций, остальные еще меньше.

В алгоритме используется минимальное покрытие
множества 16 битовых позиций параметра
тремя хорошими множествами мощности 5+5+6,
которые заданы масками $2492, $4924, $9249.

Другие три маски $04104104, $10410410, $41041041
задают три соответствующих им множества
разрешенных позиции битов результата.

Алгоритм разделяет биты параметра на три части,
каждую часть возводит в квадрат, отсекает в них
биты погрешности и соединяет части.
...
Рейтинг: 0 / 0
Микширование бит
    #40023128
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov,

У меня мозги не так хорошо работают, чтобы это понять
Но я буду стараться :)
А почему ты программируешь на D7?
...
Рейтинг: 0 / 0
Микширование бит
    #40023129
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky,

Я сейчас низкоуровневый код пишу на Си, а к Delphi/FPC/C++Builder линкую объектники
Благодаря инлайн функциям и макросам мне удаётся писать высокопроизводительный код под все 10 платформ (5 ОС по 2 битности). Для x86/x64 юзаются команды SSE2, на ARM - NEON. Пока юзаются регистры по 16 байт. Наверное на следующем уровне перейду на 32 или даже 64. Но пока так - всяко лучше, чем регистры общего назначения )
...
Рейтинг: 0 / 0
Микширование бит
    #40023131
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

мне хватает )
...
Рейтинг: 0 / 0
Микширование бит
    #40023150
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky,

Раз уже пошла такая пьянка, проиллюстрирую немного :)

Есть у меня функции AStrLen/WStrLen/CStrLen. Данная функция написана на Си, но скомпилирована в объектный файл под разные платформы и цепляется как обычная паскалевская функция:
Код: pascal
1.
2.
3.
function AStrLen(const S: PAnsiChar): NativeUInt;
function WStrLen(const S: PWideChar): NativeUInt;
function CStrLen(const S: PUCS4Char): NativeUInt;


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
REGISTER_DECL64 native_uint WStrLen(char16_t* chars)
{
    if (!chars) return 0;

    if ((native_int)chars & 1)
    {
        char16_t* _s = chars;
        for (;;)
        {
            if (*_s == 0) break;
            _s++;
        }
        return ((native_uint)_s - (native_uint)chars) >> 1;
    }

    static native_uint arr[sizeof(native_uint) / sizeof(char16_t)] = {
        0,
        ((native_uint)1 << (16 * 1)) - 1
    #if defined (LARGEINT)
        ,
        ((native_uint)1 << (16 * 2)) - 1,
        ((native_uint)1 << (16 * 3)) - 1
    #endif
    };

    char8_t* s = (char8_t*)((native_int)chars & -sizeof(native_uint));
    native_uint index = ((native_int)chars & (sizeof(native_uint) - 1)) >> 1;
    native_uint x = *((native_uint*)s) | arr[index];

    for (;;x = *((native_uint*)s))
    {
    #if defined (SMALLINT)
        if ((x & 0x0000ffff) == 0) break;
        s += sizeof(char16_t);
        if ((x & 0xffff0000) == 0) break;
        s += sizeof(char16_t);
    #else
        native_uint u = x - MASK_0001_NATIVE;
        x = ~x & u;
        if (x & MASK_8000_NATIVE) break;
        s += sizeof(native_uint);
    #endif
    }
    #if defined (LARGEINT)
    s += (bit_fastindex(x & MASK_8000_NATIVE) >> 4) * sizeof(char16_t);
    #endif

    return ((native_uint)s - (native_uint)chars) >> 1;
}



Из кода хорошо видно, что функция эффективно работает только на 64 битах, когда анализируется сразу 4 символа за итерацию. И то, если указатель выравнен на границу WideChar. Кстати я давно использую этот подход, когда через маски и битовые итерации анализируется сразу несколько символов. Минуса 2: во-первых, очень сильно расходуются регистры общего назначения, во-вторых, по сути ты можешь определить только первое вхождение, состояние остальных символов становится неизвестно. С SIMD по сути ты видишь картину целиком, плюс регистры общего назначения практически не расходуются. А на Си есть возможность зафигачить макросы и инлайн функции, что в итоге выльется в удобоваримые конструкции на несколько платформ и реализация сразу нескольких функций. Вот реализация AStrLen/WStrLen/CStrLen:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
FORCEINLINE bool InternalStrLen(char8_t** ptr_s, native_uint* ptr_mask,
  native_uint char_size, native_uint shift_bytes, block16 null, block16 CMPBLOCK16_MASKBITS)
{
    block16 xcmp, x;
    native_uint mask;
    native_uint high_clear_mask = (shift_bytes)?(0xffff >> char_size):((native_uint)-1);
    char8_t* s = *ptr_s;
    
    // first block
    block16* block = (block16*)((native_int)s & -sizeof(block16));
    native_uint invalid_bytes = ((native_uint)s - (native_uint)block - shift_bytes);
    if (!shift_bytes || (invalid_bytes != (sizeof(block16) - char_size)))
    {
        x = block16_switchshr_bytes(*block, *block, shift_bytes);
        xcmp = block16_cmpe_ex(x, null, char_size);
        mask = bitmask_clear(block16_cmpmask_ex(xcmp, CMPBLOCK16_MASKBITS), invalid_bytes) & high_clear_mask;
        if (mask) goto done;
    }  

    // block loop
    DISABLE_LOOP_UNROLL
    for (;;)
    {
        block++;
        if (shift_bytes) 
        {
            s = (uint8_t*)block + shift_bytes - char_size;
            if (StrGetChar(s, 0, char_size) == 0) 
            { 
                *ptr_s = s;
                return true;
            }    
        }

        x = block16_switchshr_bytes(*block, *block, shift_bytes);
        xcmp = block16_cmpe_ex(x, null, char_size);
        if (internal_block16_cmpmask_ex(&mask, xcmp, high_clear_mask)) goto done;
    }

done:
    *ptr_s = (uint8_t*)block + shift_bytes;
    *ptr_mask = mask; 
    return false;
}

FORCEINLINE native_uint StrLen(ptr_t chars, native_uint char_size)
{
    if (!chars) return 0;
   
    block16 null = volatile_null_block16;
    internal_block16_cmpmaskinit;

    native_uint mask;
    uint8_t* s = chars;
    if (likely(((native_int)s & (char_size - 1)) == 0))
    {
        if (InternalStrLen(&s, &mask, char_size, 0, null, CMPBLOCK16_MASKBITS)) goto done;
    }
    else if (((native_int)s & (char_size - 1)) == 1)
    {
        if (InternalStrLen(&s, &mask, char_size, 1, null, CMPBLOCK16_MASKBITS)) goto done;
    } 
    else if (((native_int)s & (char_size - 1)) == 2)
    {
        if (InternalStrLen(&s, &mask, char_size, 2, null, CMPBLOCK16_MASKBITS)) goto done;
    }
    else if (((native_int)s & (char_size - 1)) == 3)
    {
        if (InternalStrLen(&s, &mask, char_size, 3, null, CMPBLOCK16_MASKBITS)) goto done;
    }

    s += bit_fastindex(mask);

done:
    return ((native_uint)s - (native_uint)chars) / char_size;
}

REGISTER_DECL64 native_uint AStrLen(char8_t* chars)
{
    return StrLen(chars, sizeof(*chars));
}

REGISTER_DECL64 native_uint WStrLen(char16_t* chars)
{
    return StrLen(chars, sizeof(*chars));
}

REGISTER_DECL64 native_uint CStrLen(char32_t* chars)
{
    return StrLen(chars, sizeof(*chars));
}


И вот смотри, в какую красоту превращается WStrLen. По сути там 2 кейса: выравненный и невыравненный. В выравненном анализируется 8 символов за итерацию. В невыровненном 7 + 1 :)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
WStrLen: # @WStrLen
  test eax, eax
  je .LBB0_1
  push esi
  mov edx, eax
  mov ecx, eax
  xorps xmm0, xmm0
  and edx, -16
  sub ecx, edx
  test al, 1
  jne .LBB0_6
  movdqa xmm1, xmmword ptr [edx]
  pcmpeqw xmm1, xmm0
  pmovmskb esi, xmm1
  shr esi, cl
  shl esi, cl
  test esi, esi
  jne .LBB0_14
.LBB0_4: # =>This Inner Loop Header: Depth=1
  movdqa xmm1, xmmword ptr [edx + 16]
  add edx, 16
  pcmpeqw xmm1, xmm0
  pmovmskb esi, xmm1
  test esi, esi
  je .LBB0_4
.LBB0_14:
  rep bsf ecx, esi
  add ecx, edx
.LBB0_15:
  sub ecx, eax
  shr ecx
  pop esi
  mov eax, ecx
  ret
.LBB0_1:
  xor ecx, ecx
  mov eax, ecx
  ret
.LBB0_6:
  dec ecx
  cmp ecx, 14
  je .LBB0_8
  movdqa xmm1, xmmword ptr [edx]
  psrldq xmm1, 1 # xmm1 = xmm1[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero
  pcmpeqw xmm1, xmm0
  pmovmskb esi, xmm1
  shr esi, cl
  shl esi, cl
  and esi, 16383
  jne .LBB0_13
.LBB0_8:
  add edx, 15
.LBB0_9: # =>This Inner Loop Header: Depth=1
  cmp word ptr [edx], 0
  je .LBB0_10
  movdqa xmm1, xmmword ptr [edx + 1]
  add edx, 16
  psrldq xmm1, 1 # xmm1 = xmm1[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],zero
  pcmpeqw xmm1, xmm0
  pmovmskb esi, xmm1
  and esi, 16383
  je .LBB0_9
  add edx, -15
.LBB0_13:
  inc edx
  jmp .LBB0_14
.LBB0_10:
  mov ecx, edx
  jmp .LBB0_15

...
Рейтинг: 0 / 0
Микширование бит
    #40023154
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
SOFT FOR YOU
А почему ты программируешь на D7?


ну наконец-то !
...
Рейтинг: 0 / 0
Микширование бит
    #40023174
Sapersky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU
Sapersky,
Я сейчас низкоуровневый код пишу на Си, а к Delphi/FPC/C++Builder линкую объектники
Благодаря инлайн функциям и макросам мне удаётся писать высокопроизводительный код под все 10 платформ (5 ОС по 2 битности)
Да, сишные компиляторы в целом лучше подходят для низкоуровневой оптимизации. Хотя микс из разных языков затрудняет отладку, особенно линковка в виде obj - как их отлаживать из Дельфи? Только как ассемблер. Или писать тесты на Си и надеяться, что всё отладишь там.
Конкретно StrLen - странный пример. Можно подумать, сейчас часто используются нуль-терминированные строки. Или ты там всю RTL переписываешь из любви к искусству?
И кстати, какую выгоду даёт выравнивание на x86? У меня сложилось впечатление, что на современных процессорах небольшую, ну может 10%.
...
Рейтинг: 0 / 0
Микширование бит
    #40023179
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Sapersky
Хотя микс из разных языков затрудняет отладку, особенно линковка в виде obj - как их отлаживать из Дельфи?

Так же, как функции WinAPI ))
...
Рейтинг: 0 / 0
Микширование бит
    #40023181
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky,

Ну отлаживать конечно сложнее
Тут спорить не буду

Ну а что делать?
Embarcadero оптимизировать свои компиляторы не хочет
Под Linux вообще труба, ещё хуже, чем под Виндой
Ну и потом, описывая часть кода на Си, есть перспектива реюзания в Си-проектах

А насчёт примера StrLen... это просто пример
Я планирую масштабное переписывание функций обработки текстов на зиму. Пока есть несколько функций на SIMD, просто решил показать. Есть ещё CompareMem, сравнение строк. Кто хочет - может запилить бенчмарки, мне пока влом )

Насчёт выравнивания... большая тема
Но в StrLen оно имеет смысл не с точки зрения оптимизации, а с той точки зрения, что не учитывая выравнивание, ты всегда можешь попасть на недоступную страницу. Выравнивая адрес, ты всегда можешь гарантировать валидное чтение. Или условно валидное )
...
Рейтинг: 0 / 0
Микширование бит
    #40023182
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вообще заходите в наше DelphiCommunity в телеграме!
Будем обсуждать там то, что не укладывается в формат форума
...
Рейтинг: 0 / 0
Микширование бит
    #40023196
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sapersky

И кстати, какую выгоду даёт выравнивание на x86? У меня сложилось впечатление, что на современных процессорах небольшую, ну может 10%.

Без него SSE вообще не работает AFAIK.
...
Рейтинг: 0 / 0
Микширование бит
    #40023198
Фотография defecator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
SOFT FOR YOU
Я планирую масштабное переписывание функций обработки текстов на зиму


и всё, конечно же, будет самым быстрым во всём мире ?
...
Рейтинг: 0 / 0
Микширование бит
    #40023200
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
defecator
SOFT FOR YOU
Я планирую масштабное переписывание функций обработки текстов на зиму


и всё, конечно же, будет самым быстрым во всём мире ?

Ну, не самым, конечно. Но что глючить будет - это 100%.
...
Рейтинг: 0 / 0
Микширование бит
    #40023205
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvp,

Ну не
Есть aligned чтение/запись
Есть unaligned

На современных процессорах как говорят, разницы нет
По моим тестам тоже
Но кто знает, может на каких-то данных в каких-то случаях всё-таки разница есть
...
Рейтинг: 0 / 0
Микширование бит
    #40023209
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU

Ну не
Есть aligned чтение/запись
Есть unaligned

Там есть всякие функции, которые со строками работают, так вот они вроде требуют выравнивания, иначе AV или что-то такое.
...
Рейтинг: 0 / 0
Микширование бит
    #40023216
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SOFT FOR YOU

Embarcadero оптимизировать свои компиляторы не хочет
Под Linux вообще труба, ещё хуже, чем под Виндой

Под Линух же LLVM, не?
...
Рейтинг: 0 / 0
Микширование бит
    #40023217
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Fr0sT-Brutal,

В этом весь и прикол
И под ARM тоже LLVM
Только они так до сих пор и не удосужились довести его до ума
Впечатление такое, что для Debug/Release генерируется условно один и тот же код
...
Рейтинг: 0 / 0
104 сообщений из 104, показаны все 5 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Микширование бит
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]