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

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function to_num(arr: arBytes; 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;
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929042
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
20.02.2020 16:53, cptngrb пишет:
>
> Как ускорить функцию перевода массива байт в число?
>

на собеседовании шо-ле задали?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929043
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий, нет)).
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929045
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
много раз в циклах используется, хочется побыстрее
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929047
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
профилируй
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929052
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
for k:= (i+1) to j do 
  Result:=(Result shl 8) or arr[k];


Гы.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929056
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrbКак ускорить функцию перевода массива байт в число?

Перестать передавать arr по значению.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929058
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat, )
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929061
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, это да. я упростил пример. На самом деле передается объект, одним из атрибутов которого является динамический массив
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929063
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
думал, что так быстрее будет, но возвращает другое число

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
function to_num(arr: arBytes; const i,j: integer):UInt64;
var
  arr: array [0..7] of byte;
  r: UInt64 absolute arr;
begin
  move(arr[i], arr[0], (j-i)+1);
Result:= r;
end;
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929066
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
где-то туплю сильно
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929078
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не тот порядок байт
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929082
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поясни задачу

если массив содержит [1], [2], [3], [4], [5], [6], [7], [8], тебе на выходе надо получить 12345678?

если да, то твой способ вполне себе подходящий: для UInt64 это всего восемь итераций, внутри которых только сдвиг и суммирование. Это очень быстро.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929083
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача в 1-м посте написана.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929086
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

Компилируешь в 32 или 64 бита?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929088
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey, в данном случае 64
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929090
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb
Как ускорить функцию
сделать без цикла и на асме
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929092
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb
в данном случае 64

Жаль. 32-битный вариант можно было ускорить в ~2 раза :)
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929094
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey, это как?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929096
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

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

бред не ускоряют, его переписывают.

Приведи более полные примеры с вызовом этой функции,
чтобы можно было понять замысел автора.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929124
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это какое-то странное CRC.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929125
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
20.02.2020 18:43, rgreat пишет:
> Это какое-то странное CRC.

скорее странное BCD.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929126
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrbгде-то туплю сильно

Практически везде. Начиная с того, что просишь диагноз по фотографии дальнего родственника
больного. Тормоза не в том коде, который ты показал.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929129
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящийскорее странное BCD.

Вы что, предыдущие топики аффтара забыли?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929135
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что началось то? Какашки на вентилятор? Ну не знаете и не знаете. Не хотите как хотите.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929136
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov, меня интересует в этом топике ровно то, что я спросил. Архитектура, подходы и "все херня, переделывай" решил в другой раз спросить
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929139
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, Спасибо за ответ. Тему можно закрывать.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929141
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ничего и не тормозило. Ничего не зависает. Никакие ошибки не вылетают...пока) Просто хочется быстрее
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929145
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrbПросто хочется быстрее

Тебе уже сказали: профилируй. Места, стоящий оптимизации наобум ищутся плохо.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929148
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov, ага
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929154
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

Попробуйте вот это
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
function to_num(const arr: arBytes; 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;

хотя абсолютно согласен с
Dimitry Sibiryakov
Тормоза не в том коде, который ты показал.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929156
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, обратил внимание, что последний параметр в XE3 записывается в r8d несмотря на NativeInt
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929250
_Vasilisk_
cptngrb,

Попробуйте вот это
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
function to_num(const arr: arBytes; 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;

хотя абсолютно согласен с
Dimitry Sibiryakov
Тормоза не в том коде, который ты показал.



А потом почему гнобят людей которые пишут на ассемблере ?
Project Project1.exe raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929259


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function Convert(arr: array of byte): UInt64;
asm
  {$IF Defined(CPUX86)}
  mov     edx, DWORD PTR [eax]
  mov     eax, DWORD PTR [eax+4]
  bswap   edx
  bswap   eax
  {$ELSEIF Defined(CPUX64)}
  mov rax, qword ptr [arr]
  bswap  rax
  {$ENDIF}
end;



Код: 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.
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 Convert(arr: array of byte): UInt64;
asm
  {$IF Defined(CPUX86)}
  mov     edx, DWORD PTR [eax]
  mov     eax, DWORD PTR [eax+4]
  bswap   edx
  bswap   eax
  {$ELSEIF Defined(CPUX64)}
  mov rax, qword ptr [arr]
  bswap  rax
  {$ENDIF}
end;

begin
  try
    Writeln(to_num([1, 2, 3, 4, 5, 6, 7, 8], 0, 7));
    Writeln(Convert([1, 2, 3, 4, 5, 6, 7, 8]));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.

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

Сделать каст указателя unit8 в uint64?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929271
А я тут подумал что, вроде как задача тривиальная. И по этому хочу вложить в копилку всех кто ненавидит Delphi такой вот пример


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
// Example program
#include <iostream>
#include <byteswap.h>

uint64_t Calc(unsigned char  *array, int i) {
void* p = reinterpret_cast<void*>(array + i);
return bswap_64(*static_cast<uint64_t*>(p) << 8 * i);
}

int main()
{
  unsigned char abc[8] = {1,2,3,4,5,6,7, 8};
  std::cout << Calc(abc, 5) << "!\n";
}



Calc(abc, 5) = 395016

Что аналогично для функции автора
Код: 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.
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;

begin
  try
    Writeln(to_num([1, 2, 3, 4, 5, 6, 7, 8], 5, 7));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Код: sql
1.
2.
3.
4.
5.
6.
7.
Calc(unsigned char*, int):                             # @Calc(unsigned char*, int)
        movsxd  rcx, esi
        mov     rax, qword ptr [rdi + rcx]
        shl     ecx, 3
        shl     rax, cl
        bswap   rax
        ret

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

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

Кстати, если подумали что нельзя задать максимальную длину массива... Очень ошибаетесь. Это регулируется так

return bswap_64((*static_cast<uint64_t*>(p) << 8 * (2 + 3)));

Что аналогично
Writeln(to_num([1, 2, 3, 4, 5, 6, 7, 8], 2, 4));

= 197637

А так же
return bswap_64((*static_cast<uint64_t*>(p) << 8 * (1 + 5)));

Что аналогично
Writeln(to_num([1, 2, 3, 4, 5, 6, 7, 8], 1, 2));

= 515

А так же
return bswap_64((*static_cast<uint64_t*>(p) << 8 * (1 + 3)));

Что аналогично
Writeln(to_num([1, 2, 3, 4, 5, 6, 7, 8], 1, 4));

= 33752069
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929278
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный,

Да не, я без сарказма
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929303
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey
Сделать case
при желании и без кейса в принципе можно
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929339
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb
Как ускорить функцию перевода массива байт в число?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function to_num(arr: arBytes; 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;



Код: 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.
function to_num( 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;

var // тестовые данные
  a : array[0 .. 15] of byte =
    ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 );

procedure TForm11.Button1Click(Sender: TObject);
var
  i : UInt64;
begin
  i := to_num( a, 1, 5 );
end;
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929350
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
_Vasilisk_
cptngrb,

Попробуйте вот это
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
function to_num(const arr: arBytes; 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;

хотя абсолютно согласен спропущено...



А потом почему гнобят людей которые пишут на ассемблере ?
Project Project1.exe raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'.
Не нужно гнобить пишущих на ассемблере. Нужно гнобить тех, кто не понимает разницы между

Код: pascal
1.
function to_num(const arr: arBytes; const i,j: NativeInt):UInt64;



и

Код: pascal
1.
function to_num(const arr: array of Byte; const i,j: NativeInt):UInt64;



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

Какгриться, всралась ашипка:
Код: pascal
1.
2.
3.
4.
function to_num( var arr; idx, cnt : integer ) : UInt64; assembler; register;
asm
     Add     RCX,   RDX
     Mov     RAX,   QWord Ptr [RCX]


В результат одним махом читаются 8 байт. И если, например, параметр "количество байт" равен 3 и индекс элемента массива указывает на третий с конца элемент, чтение выйдет за границы массива. Правда, результат будет скорректирован операцией And .
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929459
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
А потом почему гнобят людей которые пишут на ассемблере ?
Project Project1.exe raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'.
В оригинале первый параметр функции объявлен как динамический массив. Если вам нужен открытый массив, будьте добры переписать функцию
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929464
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function Convert(arr: array of byte): UInt64;
asm
  {$IF Defined(CPUX86)}
  mov     edx, DWORD PTR [eax]
  mov     eax, DWORD PTR [eax+4]
  bswap   edx
  bswap   eax
  {$ELSEIF Defined(CPUX64)}
  mov rax, qword ptr [arr]
  bswap  rax
  {$ENDIF}
end;

Только автору нужно было вытащить определенные байты из массива, а не первые 8
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929469
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
Код: pascal
1.
2.
3.
4.
5.
6.
function to_num( var arr; idx, cnt : integer ) : UInt64; assembler; register;
asm
// если бы не требовалось получать результат по количеству байт, 
// то достаточно было бы следующих 2-х строк
     Add     RCX,   RDX
     Mov     RAX,   QWord Ptr [RCX]

И нарваться на AV
Код: pascal
1.
 i := to_num( a, Length(a) - 2, 2);

У нас доступны только два байта. А удастся ли прочитать еще 6 - большой вопрос
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929472
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_И нарваться на AV
Да я уже посыпал голову пеплом )
22084549
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929483
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_


Код: pascal
1.
2.
3.
4.
5.
asm
  mov r9, rsi
  :
  mov rsi, r9
end;



А сохранение значения регистра RSI в регистре R9 быстрее, чем сохранение в стеке?

Код: pascal
1.
2.
3.
4.
5.
asm
  Push   RSI
  :
  Pop    RSI
end;



По объему кода сохранение в стеке точно меньше в 3 раза )
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929485
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
Да я уже посыпал голову пеплом )
22084549
Polesov
Правда, результат будет скорректирован операцией And .
Результата может вообще не быть. Достаточно разместить массив на границе страницы памяти
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929486
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Polesov
Да я уже посыпал голову пеплом )
22084549
Polesov
Правда, результат будет скорректирован операцией And .
Результата может вообще не быть. Достаточно разместить массив на границе страницы памяти

Я имел ввиду, что если удастся произвести чтение 8 байт.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929487
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
А сохранение значения регистра RSI в регистре R9 быстрее, чем сохранение в стеке?
Конечно. Во-первых доступ к регистру всегда был быстрее доступа к памяти, а во вторых push, кроме собственно mov, еще и модифицирует esp
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929489
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Polesov
А сохранение значения регистра RSI в регистре R9 быстрее, чем сохранение в стеке?
Конечно. Во-первых доступ к регистру всегда был быстрее доступа к памяти, а во вторых push, кроме собственно mov, еще и модифицирует esp

Понятно. Просто привык экономить на использовании регистров )
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929516
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Polesov
А сохранение значения регистра RSI в регистре R9 быстрее, чем сохранение в стеке?
Конечно. Во-первых доступ к регистру всегда был быстрее доступа к памяти, а во вторых push, кроме собственно mov, еще и модифицирует esp
Почти так, но не совсем. Если часть стека, куда делается push, лежит в кеше процессора, то затраты по времени такие же, как регистр -> регистр.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929517
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квейд
Если часть стека, куда делается push, лежит в кеше процессора, то затраты по времени такие же, как регистр -> регистр.
+ модификация esp. Т.е. затраты все же больше в любом случае
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929533
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_
Polesov
А сохранение значения регистра RSI в регистре R9 быстрее, чем сохранение в стеке?
Конечно. Во-первых доступ к регистру всегда был быстрее доступа к памяти, а во вторых push, кроме собственно mov, еще и модифицирует esp


Сделал тест:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
procedure BalhBlah;
asm
//    Mov   R9,   RSI
//    Mov   RSI,  R9
    Push  RSI
    Pop   RSI
end;

procedure TForm11.Button1Click(Sender: TObject);
var
  b : Int64;
  e : Int64;
  i : integer;
begin
  QueryPerformanceCounter( b );
  for i := 0 to 100000000 do
    BalhBlah;
  QueryPerformanceCounter( e );
  Caption := IntToStr( e - b );
end;



По результатам 3-х измерений:

1. вариант сохранения в регистре: 636401, 637557, 641079
2. вариант сохранения через стек: 586241, 583948, 584917

OP-коды сохранения через стек однобайтовые.
Думаю, что время модификации регистра ESP на аппаратном уровне кране мало.
Отсюда и незначительный выигрыш по времени, так как Mov регистр, регистр - OP-коды трехбайтовые.
А незначительный потому, что регистр - регистр быстрее, чем регистр - память.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929588
_Vasilisk_
Только автору нужно было вытащить определенные байты из массива, а не первые 8


Пример очень гибкий
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
#include <iostream>
#include <byteswap.h>

uint64_t Calc(const uint8_t * array, int pos) {
  return *((uint64_t*)(array + pos)) << 8 * pos;
}

int main()
{
  unsigned char abc[24] = {2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2, 4, 6, 3, 2,
      5, 6, 7, 8};
  
  uint64_t f = bswap_64(Calc(abc, 0));
  f = (f << 8*7) |  Calc(abc, 8);
  f = (f << 8*7) |  Calc(abc, 8);
  
  std::cout << bswap_64(f) << "!\n";
}



Только вот Я не понял, кто врёт.. C++ или Delphi потому что последние байты всегда неверные

В c++ = 217871544892981507
В delphi = 217871544892981506
Код: 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.
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;

var
  arr: array of byte;

begin
  try
    arr := [2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2, 4, 6, 3, 2, 5, 6, 7, 8];

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

end.



Так же если мы будем 16 байт складывать
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
// Example program
// Example program
#include <iostream>
#include <byteswap.h>

uint64_t Calc(const uint8_t * array, int pos) {
  return *((uint64_t*)(array + pos)) << 8 * pos;
}

int main()
{
  unsigned char abc[16] = {2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2};
  uint64_t f = bswap_64(Calc(abc, 0));
  f = (f << 8*7) |  Calc(abc, 8);
  
  std::cout << bswap_64(f) << "!\n";
}


c++ = 217871544892981511
Delphi = 217871544892981506
Код: 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.
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;

var
  arr: array of byte;

begin
  try
    arr := [2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2];

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

end.

...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929589
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov
_Vasilisk_
пропущено...
Конечно. Во-первых доступ к регистру всегда был быстрее доступа к памяти, а во вторых push, кроме собственно mov, еще и модифицирует esp


Сделал тест:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
procedure BalhBlah;
asm
//    Mov   R9,   RSI
//    Mov   RSI,  R9
    Push  RSI
    Pop   RSI
end;

procedure TForm11.Button1Click(Sender: TObject);
var
  b : Int64;
  e : Int64;
  i : integer;
begin
  QueryPerformanceCounter( b );
  for i := 0 to 100000000 do
    BalhBlah;
  QueryPerformanceCounter( e );
  Caption := IntToStr( e - b );
end;



По результатам 3-х измерений:

1. вариант сохранения в регистре: 636401, 637557, 641079
2. вариант сохранения через стек: 586241, 583948, 584917

OP-коды сохранения через стек однобайтовые.
Думаю, что время модификации регистра ESP на аппаратном уровне кране мало.
Отсюда и незначительный выигрыш по времени, так как Mov регистр, регистр - OP-коды трехбайтовые.
А незначительный потому, что регистр - регистр быстрее, чем регистр - память.
Хммм, чуть-чуть переделал (и собрал в 32 бита, из-за вставки)


Код: 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.
unit Unit10;

interface

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

type
  TForm10 = class(TForm)
    MemoPush: TMemo;
    MemoReg: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

procedure TForm10.FormCreate(Sender: TObject);
var
  b: Int64;
  e: Int64;
  i: integer;
  a: integer;
begin
  for a := 1 to 3 do
  begin
    QueryPerformanceCounter(b);
    for i := 0 to 100000000 do
    asm
      Push  ESI
      Pop   ESI
    end;
    QueryPerformanceCounter(e);
    MemoPush.Lines.Add(IntToStr(e - b));
  end;


  for a := 1 to 3 do
  begin
    QueryPerformanceCounter(b);
    for i := 0 to 100000000 do
    asm
      Mov   EAX,   ESI
      Mov   ESI,   EAX
    end;
    QueryPerformanceCounter(e);
    MemoReg.Lines.Add(IntToStr(e - b));
  end;
end;

end.

...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929597
ВсеРазумный
Только вот Я не понял, кто врёт.. C++ или Delphi потому что последние байты всегда неверные


Врут все, в том числе и Я но больше компиляторы

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
// Example program
#include <iostream>
#include <byteswap.h>

uint64_t calcFor(const uint8_t * array, int i, int j) {
	uint64_t temp = array[i];
  for(int r = i + 1; r < j; r++)  {
	 temp = (temp << 8) | array[r];
	  std::cout << temp << "!\n";
  }

return temp;
}

int main()
{
  unsigned char abc[24] = {2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2, 4, 6, 3, 2, 5, 6, 1};
  
  std::cout << calcFor(abc, 0, 24) << "!\n";
}



Выдал
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
517!
132354!
33882629!
8673953032!
2220531976193!
568456185905409!
145524783591784711!
360856452077782787!
145531363364635398!
362540873927558665!
576743356907260164!
72346778582189064!
74031243330848771!
505254218987733761!
217871544892981506!
434883271474610692!
649653055243027462!
290485478829065731!
577306285402620674!
216456473394479621!
72624967858128134!
145247697971250689!
289922533221073152!



Delphi выдал
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
517
132354
33882629
8673953032
2220531976193
568456185905409
145524783591784711
360856452077782787
145531363364635398
362540873927558665
576743356907260164
72346778582189064
74031243330848771
505254218987733761
217871544892981506
434883271474610692
649653055243027462
290485478829065731
577306285402620674
216456473394479621
72624967858128134
145247697971250695
289922533221074689



Код: 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.
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];
    Writeln(Result);
  end;
end;

var
  arr: array of byte;

begin
  try
    arr := [2, 5, 2, 5, 8, 1, 1, 7, 3, 6, 9, 4, 8, 3, 1, 2, 4, 6, 3, 2,
      5, 6, 7, 1];

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

end.




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

Хммм, чуть-чуть переделал (и собрал в 32 бита, из-за вставки)

Действительно, хммм ...

Переделал на твой вариант 32-х битный со вставкой и сравнил в вызовом BlahBlah:

Код: powershell
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Push:
BlahBlah      Asm
640677        632305
630739        626987
625244        631055

Mov:
BlahBlah      Asm
639556        564661
633491        551562
633367        551101



Видно, что в 32-х битном варианте Mov EAX, ESI быстрее Push
Может быть, разница обусловлена битностью приложения?

Проверить 64-х битный вариант сравнения не представляется возможным из-за asm вставки.

P.S. Измерял на процессоре Intel Core i7-4790 3.6 GHz
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929613
vavan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
фасткодера на вас главного нет
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929618
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Polesov

Видно, что в 32-х битном варианте Mov EAX, ESI быстрее Push

А вот и ответ:

в 32-битном варианте OP-коды сохранения через регистр составляют 2 байта
Код: powershell
1.
2.
089F0h        mov eax,esi
089C6h        mov esi,eax


в 64-битном варианте OP-коды сохранения через регистр составляют 3 байта
Код: powershell
1.
2.
04889F0h      mov rax,rsi
04889C6h      mov rsi,rax

Сохранение через стек в обоих вариантах по одному байту.

Поэтому в 64-битном варианте сохранение через стек чуть быстрее.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929657
Кто нибудь знает, почему вот это
Код: plaintext
1.
2.
3.
uint64_t R(uint64_t c) {
    return ((uint64_t)360858655413176578 <<  2 * 8) | (uint64_t) 144115188075855872;
}



Не тоже самое что
Код: pascal
1.
2.
3.
4.
function r(): UInt64;
begin
  Result := (UInt64(360858655413176578) shl 2 * 8) or UInt64(144115188075855872);
end;



Результатом здорового языка должен стать 506938662295044096. А Delphi компилятор с лазуром такие "Братишка, я тебе покушать принёс: 11691592161297506368"

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

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

Кури доки о приоритетности операторов.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929671
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey
ВсеРазумный
В чём магия языка то???

Кури доки о приоритетности операторов.


У меня от конструкций " << 2 * 8" и " shl 2 * 8" потекли слезы умиления.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929676
rgreat,

Потому что ты не понимаешь логики работы, а оно работает как никак на сях всё правильно.


А я кстати нашёл ошибку тем временем в примере ТС

Надо с
Код: pascal
1.
 for k := (i + 1) to j do


Заменить на
Код: pascal
1.
 for k := (i + 1) to i + j do



Тогда он перестанет выводить каких 5. И
Код: pascal
1.
2.
3.
  Writeln(to_num([5, 8, 5], 0, 2)); // Тут по прежнему будет 329733

  Writeln(to_num([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 9, 2)); // А тут станет 329733 вместо 5
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929678
А я ползаю и думаю, чего у меня результаты не сходятся.. Решил покурить пример ТС и нашёл ошибку. Теперь работает как надо Хехе
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929683
Вот перевёл малёк, но уже оценить работу можно

Код: 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.
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 i + j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert(arr: array of byte): UInt64;
asm
  {$IF Defined(CPUX86)}
  mov     edx, DWORD PTR [eax]
  mov     eax, DWORD PTR [eax+4]
  bswap   edx
  bswap   eax
  {$ELSEIF Defined(CPUX64)}
  mov rax, qword ptr [arr]
  bswap  rax
  {$ENDIF}
end;

function Convert2(arr: UInt64): UInt64;
asm
  {$IF Defined(CPUX86)}
 // 64 bit!!!1 ONLY пока что 
  {$ELSEIF Defined(CPUX64)}
  mov     rax, arr
  bswap   rax
  {$ENDIF}
end;

function calc(arr: array of byte; pos, len: integer): UInt64;
begin
  Result := PUInt64(@arr[pos])^ shl (8 * (8 - len));
end;

function Test(arr: array of byte): UInt64;
var
  A, C: UInt64;
begin
  A := Convert2(calc(arr, 1, 8));
  C := Convert2(calc(arr, 9, 3));

  Result := (A shl (8 * 3)) + C;
end;

var
  arr: array of byte;

begin
  try
    arr := [1, 5, 9, 37, 69, 2, 7, 9, 62, 5, 8, 5, 6, 1, 13, 1];

    Writeln(to_num(arr, 1, 8 + 2));
    Writeln(Test(arr));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.




4972544674847066117 << Фикшенная функция ТС

4972544674847066117 << Моя функция
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929704
Не нашёл времени реализовать asm для 32 бит, реализовал только для 64. И в интернете нашёл swap

А так же добавил пример такого
Код: pascal
1.
writeln(to_num(arr, 1, 8 + 1 + 3));



Код: 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.
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 i + j do
  begin
    Result := Result shl 8;
    Result := Result or arr[k];
  end;
end;

function Convert3(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 test(arr: array of byte): UInt64;
var
  A, B, C: UInt64;
begin
  A := Convert3(arr, 1, 8);
  C := Convert3(arr, 1 + 8, 1 + 1);
  B := Convert3(arr, (1 + 8) + (1 + 1), 3);

  Result := (A shl (8 * (1 + 1)) or C) shl (8 * 3) or B;
end;

var
  arr: array of byte;

begin
  try
    arr := [1, 5, 9, 37, 69, 2, 7, 69, 62, 153, 8, 5, 6, 1, 13, 1];

    writeln(to_num(arr, 1, 8 + 1 + 3));
    writeln(test(arr));
  except
    on E: Exception do
      writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.



Думаю понятно привёл пример, если кому то взбредёт в голову реализовать цикл для 8 байт + shl пучка

Код полностью рабочий, и выдаёт те же результаты
to_num : 523893758643996161
test : 523893758643996161
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929799
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, где ошибка то? у меня в параметрах функции передается начальный и конечные позиции, а не начало и длина
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929801
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем спасибо за старания и внимание. Ассемблерские вставки буду использовать только если совсем прижмет. AQTime показывает, что и так сойдет).
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929802
cptngrb,

Как где ошибка ? Ты только на начальной позиции можешь узнать элементы. А вот со второй части ты никогда не узнаешь.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929804
cptngrb,

То есть есть строка 12345678_12345678

Ты с ошибкой в коде можешь узнать только до _ черты к примеру с 5 по 8 элемент. А вот с 10 элемента по 14 ты никогда не узнаешь с ошибкой в коде
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929806
Я кстати посмотрел те функции к примеру на asm, там люди не сделали твою ошибку.

В принципе как и Я не сделал в своём коде, от чего и умилялся в различие знаний
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929807
Но самый быстрый способ это по 8 байт shl-ээлить. А не по каждому байту в отдельности в целом, компоновкой. Ибо быстрее

Код: 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
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929808
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, то есть to_num(ar, 1, 7) или to_num(ar, 100500, 100507) вернет ошибку?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929809
cptngrb,

Да,вернёт ошибку. Ибо элементы будут неверно подсчитаны.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929811
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, не верно подсчитаны? у меня индекс К , а не i, j
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929812
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function to_num(arr: arBytes; const 0, 7: integer):UInt64;
var
  k: integer;
begin
  Result:= arr[0]; //первый раз
  for k:= 1 to 7 do begin //1, 2, 3, 4, 5, 6, 7 итого 8
    Result:= Result shl 8;
    Result:= Result or arr[k];
end;
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929813
cptngrb,

Да как же ты не понимаешь? Вот тебе пример, который наглядно демонстрирует ошибку

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

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

uses
  System.SysUtils;

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

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;

begin
  try

    Writeln('Багованная стоковая функция');

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

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

    // Тут по прежнему будет 329733
    Writeln(to_numFix([5, 8, 5], 0, 2));

    // А тут станет 329733 вместо 5
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 9, 2));

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

end.



Выведет в консоль
Код: sql
1.
2.
3.
4.
5.
6.
Багованная стоковая функция
329733
5
Фикс функции
329733
329733
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929815
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, ять, у тебя параметры (9, 2) с чего? по моей логике должно быть (9, 10). Ты понимаешь под вторым параметром len, а я последний индекс
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929816
cptngrb,

У нас есть массив

[
1 = 8,
2 = 5,
2 = 2,
3 = 7,
4 = 9,
5 = 2,
6 = 7,
7 = 9,
8 = 2,
9 = 5,
10 = 8,
11 = 5,
12 = 6,
13 = 7,
14 = 8,
15 = 1
]

По этому 9 и 2 это будет 5, 8, 5 что в итоге = 329733 о чём нам и говорит вызов
Код: pascal
1.
Writeln(to_numFix([5, 8, 5], 0, 2));
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929819
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, 9 и 2 быть не может, т.к. после 9 идут числа 10, 11, 12.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929821
cptngrb,

Ты знаешь что такое индексы ?


arr[9] + 2 элемента. В итоге будет 3 элемента которые = 329733
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929822
Вот тебе хороший пример как это должно работать

http://www.delphibasics.ru/Move.php

Точно так - же 100% Есть источник(Массив), есть начальная позиция в массиве, и есть количество байт которые мы должны подсчитать из массива
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929823
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный, откуда мне о индексах знать то. Блин, я ему про Фому, а он мне про Ерему.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929824
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Троль?
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929825
cptngrb,

Почитай как работать с массивами, и вообще как работает память.

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

http://www.delphibasics.ru/Move.php

Точно так - же 100% Есть источник(Массив), есть начальная позиция в массиве, и есть количество байт которые мы должны подсчитать из массива


Я определяю кол-во байт, как начальная позиция, например [10] и конечная, например [17]. Итого 8 байт. 64 бита. UInt64.
и в мою функцию если передать to_num(arr, 10, 17), то она вернет правильное значение
твоя функция to_num_fix(arr, 10, 8), тоже вернет правильное значение
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929827
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
cptngrb,

Почитай как работать с массивами, и вообще как работает память.

Начальный индекс, это начала массива. Он 0. А значит конец индекса байтового массива, это максимальная длина его


это трындец.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929828
cptngrb
to_num(arr, 10, 17)


Неверно, ты должен передать 18

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

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

uses
  System.SysUtils;

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

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;

begin
  try

    Writeln('Багованная стоковая функция');

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

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

    // Тут по прежнему будет 329733
    Writeln(to_numFix([5, 8, 5], 0, 2));

    // А тут станет 329733 вместо 5
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 9, 2));

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

end.



Зачем вообще передавать 18??? Если у тебя уже определена начальная позиция массива.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929829
cptngrb,

Ты мне лучше скажи. Ты вообще собираешься считать от позиции X больше 8 байтов ? Или нет. Это вообще всех волнует в топике.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929830
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
cptngrb
to_num(arr, 10, 17)

Неверно, ты должен передать 18

а вот и нет

ВсеРазумный

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

потому что могу)
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929832
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это в какое такое я число смогу считать больше 8 байт?
Ответ: нет, на большее я не замахнусь)
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929833
cptngrb
ВсеРазумный
пропущено...

Неверно, ты должен передать 18

а вот и нет


А вот и да
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929835
cptngrb
это в какое такое я число смогу считать больше 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.
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 Convert3(arr: array of byte; pos, len: integer): UInt64;
begin
  Result := Convert2(arr, pos, len);
end;






Держи и пользуйся, функция которую я привёл в сообщение 22084968


Ибо пару сообщений назад меня уверяли что ты собираешься считать больше 8 байтов
22084564

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

Короче, вот пример
Код: 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.
program Project1;

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

uses
  System.SysUtils;

function to_numFix(arr: array of byte; const i, j: integer): UInt64;
var
  k: integer;
begin
  Result := arr[i];
  for k := (i + 1) to i + 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;

begin
  try

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

    Writeln(to_numFix([5, 8, 5], 0, 2));
    Writeln(to_numFix([8, 5, 2, 7, 9, 2, 7, 9, 2, 5, 8, 5, 6, 7, 8, 1], 9, 2));


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

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

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

end.




Работает без циклов и так далее. Самая быстрая функция
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #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
Ускорить функцию перевода массива байт в число
    #39929894
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный
Polesov,

А ещё решается выравниванием массива до X%8=0 и мы получаем прирост в 1.301539 сек

Не решается.
Массив из 16 байт [0 .. 15].
Начальный индекс 13, конечный индекс 15.

В принципе, можно размер массива брать с запасом в 7 байт.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929896
Vlad F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Эк, однако, же вас, парни, всё-таки разобралО.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929897
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vlad F,
я сделал это не в целях правды, а в целях истины (c) )
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929898
Фигасе, вот это да! asm функция хуже компиляторной

Код: 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.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
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;

function to_numBytePolesov(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;
{$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;

procedure Test_to_numBytePolesov;
begin
  Writeln('Test_to_numBytePolesov');

  QueryPerformanceCounter(T3);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      to_numBytePolesov(arr, 5, 12);
  end;
  Writeln(PrintTime(T3));
end;

{$ENDIF}

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

end.



64bitTest_to_numASMPolesov - 2.202520Test_to_numBytePolesov - 6.208926Test_to_num - 2.531078Test_to_num2 - 0.900965


Ну вот если такие asm функции писать, то лучше их и вовсе не писать.


А так, вырванивание массива :) И мы не теряем 5.307961 сек
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929899
Картинка не в актуале, на неё не смотреть. Не нашёл как удалить её.
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929900
Polesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВсеРазумный,
Код: powershell
1.
Test_to_numBytePolesov - 6.208926


все дело в Shl RAX, 08h и использовании Loop
Да еще и побайтное чтение
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929917
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.
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.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
program Project1;

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

uses
  Winapi.Windows, System.SysUtils;

function FastConvertArrToUint64(const arr: array of byte;
  pos, len: integer): UInt64;
type
  TByteArray = array of byte;
var
  p: Pointer;
begin
  Result := 0;

  p := @arr[pos];

  case len - 1 of
    0:
      Result := (UInt64(TByteArray(p)[0]));
    1:
      Result := (UInt64(TByteArray(p)[1]) or (UInt64(TByteArray(p)[0]) shl 8));
    2:
      Result := (UInt64(TByteArray(p)[2]) or (UInt64(TByteArray(p)[1]) shl 8) or
        (UInt64(TByteArray(p)[0]) shl 16));
    3:
      Result := (UInt64(TByteArray(p)[3]) or (UInt64(TByteArray(p)[2]) shl 8) or
        (UInt64(TByteArray(p)[1]) shl 16) or (UInt64(TByteArray(p)[0]) shl 24));
    4:
      Result := (UInt64(TByteArray(p)[4]) or (UInt64(TByteArray(p)[3]) shl 8) or
        (UInt64(TByteArray(p)[2]) shl 16) or (UInt64(TByteArray(p)[1]) shl 24))
        or (UInt64(TByteArray(p)[0]) shl 32);
    5:
      Result := (UInt64(TByteArray(p)[5]) or (UInt64(TByteArray(p)[4]) shl 8) or
        (UInt64(TByteArray(p)[3]) shl 16) or (UInt64(TByteArray(p)[2]) shl 24))
        or (UInt64(TByteArray(p)[1]) shl 32) or
        (UInt64(TByteArray(p)[0]) shl 40);
    6:
      Result := (UInt64(TByteArray(p)[6]) or (UInt64(TByteArray(p)[5]) shl 8) or
        (UInt64(TByteArray(p)[4]) shl 16) or (UInt64(TByteArray(p)[3]) shl 24))
        or (UInt64(TByteArray(p)[2]) shl 32) or
        (UInt64(TByteArray(p)[1]) shl 40) or (UInt64(TByteArray(p)[0]) shl 48);
    7:
      Result := (UInt64(TByteArray(p)[7]) or (UInt64(TByteArray(p)[6]) shl 8) or
        (UInt64(TByteArray(p)[5]) shl 16) or (UInt64(TByteArray(p)[4]) shl 24))
        or (UInt64(TByteArray(p)[3]) shl 32) or
        (UInt64(TByteArray(p)[2]) shl 40) or (UInt64(TByteArray(p)[1]) shl 48)
        or (UInt64(TByteArray(p)[0]) shl 56);
  end;

end;

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;

function to_numBytePolesov(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;
{$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;

procedure Test_to_num3;
begin
  Writeln('FastConvertArrayToUint64');
  QueryPerformanceCounter(T);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      FastConvertArrToUint64(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;

procedure Test_to_numBytePolesov;
begin
  Writeln('Test_to_numBytePolesov');

  QueryPerformanceCounter(T3);
  for A := 1 to 3 do
  begin
    for i := 0 to 100000000 do
      to_numBytePolesov(arr, 5, 12);
  end;
  Writeln(PrintTime(T3));
end;

{$ENDIF}

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

end.



64 bitTest_to_numASMPolesov 2.276581Test_to_numBytePolesov 6.273596Test_to_num 2.559063Test_to_num2 0.910266FastConvertArrayToUint64 1.919095

32bitTest_to_num 11.720721Test_to_num2 3.017298FastConvertArrayToUint64 5.115628


То есть быстрее может и мой ASM но коль вы говорите что 1 раз 1000000000000000 может сработать av то лучший вариант FastConvertArrayToUint64
...
Рейтинг: 0 / 0
Ускорить функцию перевода массива байт в число
    #39929980
Но я всё равно рекомендую использовать свою функцию

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



Просто выделив на 8 элементов больше, и никогда их не использовать.
Код: pascal
1.
countElements := Length(arr) - 8; 
...
Рейтинг: 0 / 0
133 сообщений из 133, показаны все 6 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ускорить функцию перевода массива байт в число
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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