powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ускорить функцию перевода массива байт в число
25 сообщений из 133, страница 5 из 6
Ускорить функцию перевода массива байт в число
    #39929839
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
видимо не работает
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929841
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
до этого индексы взял неправильные, теперь с первого элемента 8 байт
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929844
cptngrb,



Код: pascal
1.
2.
3.
4.
5.
6.
    Writeln('Фикс функции');
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 1, 7 - 1));


    Writeln('Новая функция Convert2');
    Writeln(Convert2([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 1, 8 - 1));





Фикс функции
1409604122707721
Новая функция Convert2
1409604122707721
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929846
cptngrb,

Код: pascal
1.
2.
3.
4.
5.
    Writeln('Фикс функции');
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 1, 7));

    Writeln('Новая функция Convert2');
    Writeln(Convert2([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 1, 8));



Фикс функции
360858655413176578
Новая функция Convert2
360858655413176578


Код: pascal
1.
2.
3.
4.
5.
    Writeln('Фикс функции');
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 47, 5, 8, 5, 6, 7, 8, 1], 1, 7));

    Writeln('Новая функция Convert2');
    Writeln(Convert2( [8, 5, 2, 7, 9, 2, 7, 9, 47, 5, 8, 5, 6, 7, 8, 1], 1, 8));



Фикс функции
360858655413176623
Новая функция Convert2
360858655413176623

...То есть 47 это 8 элемент для 1 и 7
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929848
В общем учёл твои пожелания. Вот

Код: 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.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

function to_num(arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert2(arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

function to_num2(arr: array of byte; const i, j: integer): UInt64;
begin
  Result := Convert2(arr, i, j - i + 1);
end;

begin
  try

    Writeln('Фикс функции');

    Writeln(to_num([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 5 + 2));

    Writeln('Новая функция Convert2');

    Writeln(to_num2([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 5 + 2));

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




Код: pascal
1.
2.
3.
4.
function to_num2(arr: array of byte; const i, j: integer): UInt64;
begin
  Result := Convert2(arr, i, j - i + 1);
end;




Теперь она работает точно так же как твоя функция в стоке
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929850
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
прогоню профайлером, посмотрю насколько быстрее
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929851
cptngrb,

Для 64 бита должно быть многократно быстрее, ибо

Код: pascal
1.
2.
3.
4.
5.
6.
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax



Это в общем то вся функция. А вот для 32 бита надо аналогично написать, а в 32 бите я плохо ассемблер знаю
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929852
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
var
 c : cardinal;
begin
  Writeln('Фикс функции');
  c:=GetTickCount;
  for var i:=0 to 100000000 do begin
    to_num([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 5 + 2);
  end;
  Writeln((GetTickCount-c).ToString+' ms');

  Writeln('Новая функция Convert2');
  c:=GetTickCount;
  for var i:=0 to 100000000 do begin
    to_num2([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 5 + 2);
  end;
  Writeln((GetTickCount-c).ToString+' ms');

  Readln;
end.



x86
Код: plaintext
1.
2.
3.
4.
Фикс функции
890 ms
Новая функция Convert2
1828 ms


x64
Код: plaintext
1.
2.
3.
Фикс функции
1625 ms
Новая функция Convert2
1718 ms


Гы-гы.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929853
rgreat,

Тест Г ибо не имеет ничего общего с измерением скорости. Когда в общий asm лист навален весь код
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929854
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конечно конечно.

...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929855
rgreat,

Кхм.

Код: 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.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Winapi.Windows, System.SysUtils;

function to_num(arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert2(arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

function to_num2(arr: array of byte; const i, j: integer): UInt64;
begin
  Result := Convert2(arr, i, j - i + 1);
end;

procedure Test_to_num;
begin
  to_num([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 5 + 7);
end;

procedure Test_to_num2;
begin
  Convert2([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 5, 7 + 1);
end;

var
  b: Int64;
  e: Int64;
  i: integer;
  a: integer;

begin
  try
    Writeln('Test_to_num2');
    QueryPerformanceCounter(b);
    for a := 1 to 3 do
    begin
      for i := 0 to 10000000 do
        Test_to_num2;
    end;
    QueryPerformanceCounter(e);
    Writeln(IntToStr(e - b));

    Writeln('Test_to_num');
    QueryPerformanceCounter(b);
    for a := 1 to 3 do
    begin
      for i := 0 to 10000000 do
        Test_to_num;
    end;
    QueryPerformanceCounter(e);
    Writeln(IntToStr(e - b));

  except
    on e: Exception do
      Writeln(e.ClassName, ': ', e.Message);
  end;
  Readln;

end.



Нормальный Качественный и объективный тест


64bit
Test_to_num2
385577
Test_to_num
3362881


32bit
Test_to_num2
2012273
Test_to_num
3879562
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929856
rgreat,

Функция даже без asm быстрее
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929860
Собрал все функции из топика. И моя функция настоящий лидер!

Код: 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.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Winapi.Windows, System.SysUtils;

function to_num(const arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert2(const arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

{$IF Defined(CPUX64)}

function to_numASM(const arr: array of byte; const i, j: NativeInt): UInt64;
asm
  mov r9, rsi
  add rcx, rdx
  mov rsi, rcx
  mov rcx, r8
  sub rcx, rdx
  inc rcx
  xor rax, rax
@start:
  shl rax, 8
  lodsb
  loop @start
  mov rsi, r9
end;

function to_numASMPolesov(var arr; idx, cnt: integer): UInt64;
  assembler; register;
asm
  // если бы не требовалось получать результат по количеству байт,
  // то достаточно было бы следующих 2-х строк
  Add     RCX,   RDX
  Mov     RAX,   QWord Ptr [RCX]

  Cmp     R8,    01h
  Ja      @@02

  Mov     RCX,   00000000000000FFh
  Jmp     @@and

@@02:
  Cmp     R8,    02h
  Ja      @@03

  Mov     RCX,   000000000000FFFFh
  Jmp     @@and

@@03:
  Cmp     R8,    03h
  Ja      @@04

  Mov     RCX,   0000000000FFFFFFh
  Jmp     @@and

@@04:
  Cmp     R8,    04h
  Ja      @@05

  Mov     RCX,   00000000FFFFFFFFh
  Jmp     @@and

@@05:
  Cmp     R8,    05h
  Ja      @@06

  Mov     RCX,   000000FFFFFFFFFFh
  Jmp     @@and

@@06:
  Cmp     R8,    06h
  Ja      @@07

  Mov     RCX,   0000FFFFFFFFFFFFh
  Jmp     @@and

@@07:
  Cmp     R8,    07h
  Ja      @@ret

  Mov     RCX,   00FFFFFFFFFFFFFFh

@@and:
  And     RAX,   RCX

@@ret:
end;
{$ENDIF}
var
  arr: array [0 .. 15] of byte = (
    8,
    5,
    2,
    7,
    9,
    2,
    7,
    9,
    2,
    5,
    8,
    5,
    6,
    7,
    8,
    1
  );

procedure Test_to_num;
begin
  to_num(arr, 5, 5 + 7);
end;

procedure Test_to_num2;
begin
  Convert2(arr, 5, 7 + 1);
end;
{$IF Defined(CPUX64)}

procedure Test_to_numASM;
begin
  to_numASM(arr, 5, 7 + 1);
end;

procedure Test_to_numASMPolesov;
begin
  to_numASMPolesov(arr, 5, 7 + 1);
end;
{$ENDIF}

var
  b: Int64;
  e: Int64;
  i: integer;
  a: integer;

begin
  try
{$IF Defined(CPUX64)}
    { Теста не будет, выбивает оишбку 'c0000005 ACCESS_VIOLATION'.
      Writeln('Test_to_numASM');
      QueryPerformanceCounter(b);
      for a := 1 to 3 do
      begin
      for i := 0 to 10000000 do
      Test_to_numASM;
      end;
      QueryPerformanceCounter(e);
      Writeln(IntToStr(e - b));
    }

    Writeln('Test_to_numASMPolesov');
    QueryPerformanceCounter(b);
    for a := 1 to 3 do
    begin
      for i := 0 to 10000000 do
        Test_to_numASMPolesov;
    end;
    QueryPerformanceCounter(e);
    Writeln(IntToStr(e - b));

{$ENDIF}
    Writeln('Test_to_num2');
    QueryPerformanceCounter(b);
    for a := 1 to 3 do
    begin
      for i := 0 to 10000000 do
        Test_to_num2;
    end;
    QueryPerformanceCounter(e);
    Writeln(IntToStr(e - b));

    Writeln('Test_to_num');
    QueryPerformanceCounter(b);
    for a := 1 to 3 do
    begin
      for i := 0 to 10000000 do
        Test_to_num;
    end;
    QueryPerformanceCounter(e);
    Writeln(IntToStr(e - b));

  except
    on e: Exception do
      Writeln(e.ClassName, ': ', e.Message);
  end;
  Readln;

end.




64 bit

Test_to_numASMPolesov : 767533
Test_to_num2 : 352728
Test_to_num : 915065


32 bit
Test_to_num2 : 875247
Test_to_num : 3017126


Функция _Vasilisk_ так и не захотела работать никак. По этому Я изначально и сказал что она работать не будет.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929862
Оказалось что Test_to_numASMPolesov вообще даже не конкурент, там совсем другие значения

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure Test_to_numASMPolesov;
begin
  Writeln('Test_to_numASMPolesov');
  Writeln(to_numASMPolesov(arr, 5, 6));
  Writeln(to_numASMPolesov(arr, 5, 7));
  Writeln(to_numASMPolesov(arr, 5, 8));
  Writeln(to_numASMPolesov(arr, 5, 9));
  Writeln(to_numASMPolesov(arr, 5, 5 + 6));
  Writeln(to_numASMPolesov(arr, 5, 5 + 7));
  Writeln(to_numASMPolesov(arr, 5, 5 + 8));
  Writeln(to_numASMPolesov(arr, 5, 5 + 9));
end;



Код: 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.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
Test_to_numASMPolesov
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
Test_to_numASMPolesov
8817602004738
1416192485558018
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
433761756713125634
47171





Test_to_num2
Test_to_num2
146095417191826694
Test_to_num2
146095417191826694
Test_to_num2
146095417191826694
Test_to_num2
146095417191826694
Test_to_num2
146095417191826694
Test_to_num2
146095417191826694
39120


Test_to_num
Test_to_num
146095417191826694
Test_to_num
146095417191826694
Test_to_num
146095417191826694
Test_to_num
146095417191826694
Test_to_num
146095417191826694
Test_to_num
146095417191826694
32325

...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929864
Ого на сколько быстрее, нашёл вывод в сек

65bit

Test_to_num : 2.545933
Test_to_num2 : 0.802596


32bit
Test_to_num : 11.633120
Test_to_num2 : 3.001649

Код: 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.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Winapi.Windows, System.SysUtils;

function to_num(const arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert2(const arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

var
  arr: array [0 .. 15] of byte = (
    8,
    5,
    2,
    7,
    9,
    2,
    7,
    9,
    2,
    5,
    8,
    5,
    6,
    7,
    8,
    1
  );

  T: Int64;
  i, A: integer;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

procedure Test_to_num;
begin
  Writeln('Test_to_num');
  QueryPerformanceCounter(T);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      to_num(arr, 5, 5 + 7);
  end;
  Writeln(PrintTime(T));

end;

procedure Test_to_num2;
begin
  Writeln('Test_to_num2');
  QueryPerformanceCounter(T);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      Convert2(arr, 5, 7 + 1);
  end;
  Writeln(PrintTime(T));

end;

begin
  try
    Test_to_num;
    Test_to_num2;
  except
    on e: Exception do
      Writeln(e.ClassName, ': ', e.Message);
  end;
  Readln;

end.

...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929870
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Оказалось что Test_to_numASMPolesov вообще даже не конкурент, там совсем другие значения

Там третьей строчкой надо добавить
Код: powershell
1.
Bswap   RAX



ВсеРазумный
Код: powershell
1.
mov     rax, qword ptr [arr + rax]


Та же самая ошибка, что и у меня - возможно чтение за границами массива.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929871
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.
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.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Winapi.Windows, System.SysUtils;

function to_num(const arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert2(const arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

{$IF Defined(CPUX64)}

function to_numASMPolesov(var arr; idx, cnt: integer): UInt64;
  assembler; register;
asm
  // если бы не требовалось получать результат по количеству байт,
  // то достаточно было бы следующих 2-х строк
  Add     RCX,   RDX
  Mov     RAX,   QWord Ptr [RCX]
  Bswap   RAX

  Cmp     R8,    01h
  Ja      @@02

  Mov     RCX,   00000000000000FFh
  Jmp     @@and

@@02:
  Cmp     R8,    02h
  Ja      @@03

  Mov     RCX,   000000000000FFFFh
  Jmp     @@and

@@03:
  Cmp     R8,    03h
  Ja      @@04

  Mov     RCX,   0000000000FFFFFFh
  Jmp     @@and

@@04:
  Cmp     R8,    04h
  Ja      @@05

  Mov     RCX,   00000000FFFFFFFFh
  Jmp     @@and

@@05:
  Cmp     R8,    05h
  Ja      @@06

  Mov     RCX,   000000FFFFFFFFFFh
  Jmp     @@and

@@06:
  Cmp     R8,    06h
  Ja      @@07

  Mov     RCX,   0000FFFFFFFFFFFFh
  Jmp     @@and

@@07:
  Cmp     R8,    07h
  Ja      @@ret

  Mov     RCX,   00FFFFFFFFFFFFFFh

@@and:
  And     RAX,   RCX

@@ret:
end;
{$ENDIF}
var
  arr: array [0 .. 15] of byte = (
    8,
    5,
    2,
    7,
    9,
    2,
    7,
    9,
    2,
    5,
    8,
    5,
    6,
    7,
    8,
    1
  );

var
  T, T1, T3: Int64;
  i, A: integer;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): integer; cdecl;
  varargs; external 'msvcrt.dll';

function PrintTime(T: Int64): AnsiString;
var
  A, b: Int64;
begin
  Result := '';
  if QueryPerformanceCounter(A) and QueryPerformanceFrequency(b) then
  begin
    SetLength(Result, 25);
    SetLength(Result, sprintf(PAnsiChar(Result), '%f', single((A - T) / b)));
  end;
end;

procedure Test_to_num;
begin
  Writeln('Test_to_num');
  QueryPerformanceCounter(T1);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      to_num(arr, 5, 5 + 7);
  end;
  Writeln(PrintTime(T1));
end;

procedure Test_to_num2;
begin
  Writeln('Test_to_num2');
  QueryPerformanceCounter(T);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      Convert2(arr, 5, 7 + 1);
  end;
  Writeln(PrintTime(T));
end;

{$IF Defined(CPUX64)}

procedure Test_to_numASMPolesov;
begin
  Writeln('Test_to_numASMPolesov');

  QueryPerformanceCounter(T3);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      to_numASMPolesov(arr, 5, 8);
  end;
  Writeln(PrintTime(T3));
end;
{$ENDIF}

begin
  try
{$IF Defined(CPUX64)}Test_to_numASMPolesov; {$ENDIF}
    Test_to_num;
    Test_to_num2;
  except
    on e: Exception do
      Writeln(e.ClassName, ': ', e.Message);
  end;
  Readln;

end.




64bitTest_to_numASMPolesov2.201521Test_to_num3.024955Test_to_num20.899982

Быстрее, но не быстрее чем моя


Polesov
Та же самая ошибка, что и у меня - возможно чтение за границами массива.



Если только сам автор её не сделает, ибо код равен
Код: pascal
1.
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929880
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумныйPolesovТа же самая ошибка, что и у меня - возможно чтение за границами массива.Если только сам автор её не сделаетПараметры функции, если не ошибаюсь, ссылка на массив байт, начальный и конечный индексы массива. Так?

Пример: массив из 10 элементов array[0 .. 9] of byte;
Индексы с 7 по 9 (3 байта)
Вопрос:
Код: powershell
1.
mov     rax, qword ptr [arr + rax]

откуда будет произведено чтение 8 байт?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929882
Polesov,

Так сам автор сказал, что он не собирается читать больше 8 байт. И у него есть определённая информация по количеству байтов, которые он может прочитать. Цитата

cptngrb

ВсеРазумный

Зачем вообще передавать 18??? Если у тебя уже определена начальная позиция массива.

потому что могу)



Ограничение можно поставить, X MOD 9 но надо ли оно?


Так что в ногу выстрелить, можно... Но получиться ли, если человек даёт правильные данные ?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929884
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Polesov,

Так сам автор сказал, что он не собирается читать больше 8 байт. И у него есть определённая информация по количеству байтов, которые он может прочитать. Цитата

cptngrb

пропущено...

потому что могу)



Ограничение можно поставить, X MOD 9 но надо ли оно?


Так что в ногу выстрелить, можно... Но получиться ли, если человек даёт правильные данные ?


Э-э-э... Дело не в том, что автор "не собирается читать больше 8 байт".
Дело в том, что при в приведенном мной примере надо прочитать последние 3 байта массива,
а будет произведено чтение 8 байт, 5 из которых за границами массива.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929885
Polesov,

С чего ради будет произведено чтение 8 байт? Когда будет произведено чтение 2 байт + 1 байт первого элемента, в итоге 3 байта



Код: pascal
1.
  Writeln(Convert2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7, 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.
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

function Convert2(arr: array of byte; pos, len: integer): UInt64;
{$IF Defined(CPUX86)}
var
  Lo, Hi: Cardinal;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));

  Lo := Int64Rec(Result).Hi;
  Hi := Int64Rec(Result).Lo;
  Int64Rec(Result).Hi := (Hi shr 24) or ((Hi and $00FF0000) shr 8) or
    ((Hi and $0000FF00) shl 8) or (Hi shl 24);
  Int64Rec(Result).Lo := (Lo shr 24) or ((Lo and $00FF0000) shr 8) or
    ((Lo and $0000FF00) shl 8) or (Lo shl 24);
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]
  lea     ecx, [8*len]
  neg     cl
  shl     rax, cl
  bswap   rax
  {$ENDIF}
end;

begin

  Writeln(Convert2([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 7, 2));

  Readln;

end.




... Отредактировал, убрав лишний код тестирования
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929889
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arr - массив из 10 байт [0 .. 9]
Pos - 7-й элемент массива
ВсеРазумный

Код: powershell
1.
2.
3.
4.
{$ELSEIF Defined(CPUX64)}
asm
  movsxd  rax, pos
  mov     rax, qword ptr [arr + rax]



Сколько всего байт будет прочитано в RAX?
Откуда будут прочитаны старшие 5 байт?

P.S. Ну, я уже не знаю, как объяснить ...
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929890
Polesov,

Тогда тут тоже будет ошибка

Код: pascal
1.
  Result := PUInt64(@arr[pos])^;



А значит, надо просто следить за тем, какой размер массива -какая позиция, и максимальная длина массива.


То есть проблема не ASM кода, а проблема глобальная.


Хочу кстати подметить, что проблема решается во всех случаях, обзаведясь ещё одним аргументом - максимальной длины. А так, никак не решается
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929891
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Хочу кстати подметить, что проблема решается во всех случаях, обзаведясь ещё одним аргументом - максимальной длины. А так, никак не решается

Решается.
Например, побайтовым чтением элементов массива.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
function to_num( var arr; ofs, fin : integer ) : UInt64; assembler; register;
asm
     Push    RSI

     Mov     RSI,   RCX
     Add     RSI,   RDX

     Mov     RCX,   R8
     Sub     RCX,   RDX
     Inc     RCX
     Xor     RAX,   RAX

@@10:
     Shl     RAX,   08h
     LodsB
     Loop    @@10

     Pop     RSI
end;

Но скорость будет ниже, естественно.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929893
Polesov,

А ещё решается выравниванием массива до X%8=0 и мы получаем прирост в 1.301539 сек
...
Рейтинг: 0 / 0
25 сообщений из 133, страница 5 из 6
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ускорить функцию перевода массива байт в число
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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