Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.03.2013, 12:40   #1
vvvch
 
Регистрация: 11.03.2013
Сообщений: 5
По умолчанию Профилирование

Я не большой специалист в программировании и много не знаю. Сделал две функции (метода) одна на паскале, другая на ассемблере. Они почти одинаковые, делают одно и то-же (вычисляют контрольную сумму (СRС16) для Modbus) Они работают правильно - я проверял, но... Я не знаю стоит-ли использовать ассемблер для ускорения или не заморачиваться с этим и делать на паскале. Когда - то, я помню, время выполнения пожно было выяснить профилированием, но это под дос, а сейчас у меня таких инструментов нет. Вот я и привожу текст функций, если у кого он(профайлер) есть выясните пожалуйста стоит ли использовать паскаль или ассемблер версию (или это всё равно). Функция будет вызываться очень часто, параметром будет буфер не более 100 байт (очень редко больше).
Вот функции:
Код:
function TfCalcCRC.CalcCRC(var buf : array of byte; const len : integer) : word;
  // CRC = $CB72   $0924
type
  TWord = record
    lo, hi  : byte
  end;
var
  i : integer;
  j : byte;
const
  CRC_st = $FFFF;
  CRC_1  = $A001;
begin
  Result := CRC_st;
  for i := 0 to len - 1 do
  begin
    TWord(Result).lo := TWord(Result).lo xor Buf[i];
    for j := 0 to 7 do
      if boolean(Result and 1) then
        Result := (Result shr 1) xor CRC_1
      else
        Result := Result shr 1;
  end;
end;

{$ASMMODE intel}
//{$OUTPUT_FORMAT BASM}
function TfCalcCRC.CalcCRCasm(var buf : array of byte; const len : integer) : word;
  assembler;
const
  CRC_st = $FFFF;
  CRC_1  = $A001;
asm
   //EDX - Указывает на передаваемые параметры
   //Можно менять EAX ECX ??EDX
   //Сохранить в стэке EBX ESI EDI ESP EBP не менять DS ES SS CS FS GS
   PUSH ESI
   MOV     AX, CRC_st  //AX - Result
   XOR     ESI, ESI    //ESI - цикл по буферу 0,1,2...len-1
@loop1:
   XOR     AL, byte ptr [buf+ESI] //TWord(Result).lo := TWord(Result).lo xor Buf[i];
   MOV CX, 8 //цикл 8 раз
@loop2:
   //if boolean(Result and 1) then
   TEST AX, 1 //and с установкой флагов без изменения акамулятора
   JZ @m1 //Переход если 0
   SHR AX, 1 //Result := (Result shr 1) xor CRC_1
   XOR AX, CRC_1
   JMP @m2
@m1: // Result := Result shr 1;
   SHR AX, 1
@m2:
   LOOP @loop2
   INC     ESI                // Организуем т.о
   CMP     ESI, dword ptr len // цикл по буферу
   JB      @loop1              // --------------
   //в AX -  результат
   //
   pop ESI
end;
Я не большой специалист в программировании, по этому если увидите ошибки (а их наварно не мало) сообщите.
Для профилирования я написал небольшую отладочную програмку но она на Lazarus (впрочем это не важно ассемблер вроде не использует ничего, что не работало бы под Delphi). Файл я приложил.
Очень прошу - помогите.
Вложения
Тип файла: rar CRC.rar (125.2 Кб, 5 просмотров)
vvvch вне форума Ответить с цитированием
Старый 11.03.2013, 13:38   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Я бы это в паскале оставил. Практических различий в скорости быть не должно. Не настолько там уж код тяжелый.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 11.03.2013, 14:03   #3
vvvch
 
Регистрация: 11.03.2013
Сообщений: 5
По умолчанию

Разница в коде:
Код:
function TfCalcCRC.CalcCRC(var buf : array of byte; const len : integer) : word;
  // CRC = $CB72   $0924
type
  TWord = record
    lo, hi  : byte
  end;
var
  i : integer;
  j : byte;
const
  CRC_st = $FFFF;
  CRC_1  = $A001;
begin
  //ucalccrc.pas:75                   begin
  //00424C00 55                       push   %ebp
  //00424C01 89e5                     mov    %esp,%ebp
  //00424C03 83ec18                   sub    $0x18,%esp
  //00424C06 8945f4                   mov    %eax,-0xc(%ebp)
  //00424C09 8955fc                   mov    %edx,-0x4(%ebp)
  //00424C0C 894df8                   mov    %ecx,-0x8(%ebp)
  //ucalccrc.pas:77                   Result := CRC_st;
  //00424C0F 66c745f0ffff             movw   $0xffff,-0x10(%ebp)
  //ucalccrc.pas:78                   for i := 0 to len - 1 do
  //00424C15 8b4508                   mov    0x8(%ebp),%eax
  //00424C18 48                       dec    %eax
  //00424C19 c745ec00000000           movl   $0x0,-0x14(%ebp)
  //00424C20 3b45ec                   cmp    -0x14(%ebp),%eax
  //00424C23 7c50                     jl     0x424c75 <TFCALCCRC__CALCCRC+117>
  //00424C25 ff4dec                   decl   -0x14(%ebp)
  //00424C28 ff45ec                   incl   -0x14(%ebp)
  //ucalccrc.pas:80                   TWord(Result).lo := TWord(Result).lo xor Buf[i];
  //00424C2B 8b4dfc                   mov    -0x4(%ebp),%ecx
  //00424C2E 8b55ec                   mov    -0x14(%ebp),%edx
  //00424C31 8a1411                   mov    (%ecx,%edx,1),%dl
  //00424C34 8a4df0                   mov    -0x10(%ebp),%cl
  //00424C37 30ca                     xor    %cl,%dl
  //00424C39 8855f0                   mov    %dl,-0x10(%ebp)
  //ucalccrc.pas:81                   for j := 0 to 7 do
  //00424C3C c645e800                 movb   $0x0,-0x18(%ebp)
  //00424C40 fe4de8                   decb   -0x18(%ebp)
  //00424C43 90                       nop
  //00424C44 fe45e8                   incb   -0x18(%ebp)
  //ucalccrc.pas:82                   if boolean(Result and 1) then
  //00424C47 668b55f0                 mov    -0x10(%ebp),%dx
  //00424C4B 6681e20100               and    $0x1,%dx
  //00424C50 84d2                     test   %dl,%dl
  //00424C52 7412                     je     0x424c66 <TFCALCCRC__CALCCRC+102>
  //ucalccrc.pas:83                   Result := (Result shr 1) xor CRC_1
  //00424C54 0fb755f0                 movzwl -0x10(%ebp),%edx
  //00424C58 d1ea                     shr    %edx
  //00424C5A 81f201a00000             xor    $0xa001,%edx
  //00424C60 668955f0                 mov    %dx,-0x10(%ebp)
  //00424C64 eb04                     jmp    0x424c6a <TFCALCCRC__CALCCRC+106>
  //ucalccrc.pas:85                   Result := Result shr 1;
  //00424C66 66d16df0                 shrw   -0x10(%ebp)
  //00424C6A 807de807                 cmpb   $0x7,-0x18(%ebp)
  //00424C6E 72d4                     jb     0x424c44 <TFCALCCRC__CALCCRC+68>
  //00424C70 3b45ec                   cmp    -0x14(%ebp),%eax
  //00424C73 7fb3                     jg     0x424c28 <TFCALCCRC__CALCCRC+40>
  //ucalccrc.pas:87                   end;
  //00424C75 668b45f0                 mov    -0x10(%ebp),%ax
  //00424C79 c9                       leave
  //00424C7A c20400                   ret    $0x4

  Result := CRC_st;
  for i := 0 to len - 1 do
  begin
    TWord(Result).lo := TWord(Result).lo xor Buf[i];
    for j := 0 to 7 do
      if boolean(Result and 1) then
        Result := (Result shr 1) xor CRC_1
      else
        Result := Result shr 1;
  end;
end;
(Функция будет очень часто вызываться)
vvvch вне форума Ответить с цитированием
Старый 11.03.2013, 14:04   #4
vvvch
 
Регистрация: 11.03.2013
Сообщений: 5
По умолчанию

Код:
{$ASMMODE intel}
//{$OUTPUT_FORMAT BASM}
function TfCalcCRC.CalcCRCasm(var buf : array of byte; const len : integer) : word;
  assembler;
const
  CRC_st = $FFFF;
  CRC_1  = $A001;
asm
   00424C80 55                       push   %ebp
   00424C81 89e5                     mov    %esp,%ebp
   00424C83 83ec04                   sub    $0x4,%esp
   //ucalccrc.pas:100                  PUSH ESI
   //00424C86 56                       push   %esi
   //ucalccrc.pas:101                  MOV     AX, CRC_st  //AX - Result
   //00424C87 66b8ffff                 mov    $0xffff,%ax
   //ucalccrc.pas:102                  XOR     ESI, ESI    //ESI - цикл по буферу 0,1,2...len-1
   //00424C8B 31f6                     xor    %esi,%esi
   //ucalccrc.pas:104                  XOR     AL, byte ptr [buf+ESI] //TWord(Result).lo := TWord(Result).lo xor Buf[i];
   //00424C8D 320432                   xor    (%edx,%esi,1),%al
   //ucalccrc.pas:105                  MOV CX, 8 //цикл 8 раз
   //00424C90 66b90800                 mov    $0x8,%cx
   //ucalccrc.pas:108                  TEST AX, 1 //and с установкой флагов без изменения акамулятора
   //00424C94 66a90100                 test   $0x1,%ax
   //ucalccrc.pas:109                  JZ @m1 //Переход если 0
   //00424C98 7409                     je     0x424ca3 <TFCALCCRC__CALCCRCASM+35>
   //ucalccrc.pas:110                  SHR AX, 1 //Result := (Result shr 1) xor CRC_1
   //00424C9A 66d1e8                   shr    %ax
   //ucalccrc.pas:111                  XOR AX, CRC_1
   //00424C9D 663501a0                 xor    $0xa001,%ax
   //ucalccrc.pas:112                  JMP @m2
   //00424CA1 eb03                     jmp    0x424ca6 <TFCALCCRC__CALCCRCASM+38>
   //ucalccrc.pas:114                  SHR AX, 1
   //00424CA3 66d1e8                   shr    %ax
   //ucalccrc.pas:116                  LOOP @loop2
   //00424CA6 e2ec                     loop   0x424c94 <TFCALCCRC__CALCCRCASM+20>
   //ucalccrc.pas:117                  INC     ESI                // Организуем т.о
   //00424CA8 46                       inc    %esi
   //ucalccrc.pas:118                  CMP     ESI, dword ptr len // цикл по буферу
   //00424CA9 3b7508                   cmp    0x8(%ebp),%esi
   //ucalccrc.pas:119                  JB      @loop1              // --------------
   //00424CAC 72df                     jb     0x424c8d <TFCALCCRC__CALCCRCASM+13>
   //ucalccrc.pas:122                  pop ESI
   //00424CAE 5e                       pop    %esi
   //ucalccrc.pas:123                  end;
   //00424CAF c9                       leave
   //00424CB0 c20400                   ret    $0x4

   //EDX - Указывает на передаваемые параметры
   //Можно менять EAX ECX ??EDX
   //Сохранить в стэке EBX ESI EDI ESP EBP не менять DS ES SS CS FS GS
   PUSH ESI
   MOV     AX, CRC_st  //AX - Result
   XOR     ESI, ESI    //ESI - цикл по буферу 0,1,2...len-1
@loop1:
   XOR     AL, byte ptr [buf+ESI] //TWord(Result).lo := TWord(Result).lo xor Buf[i];
   MOV CX, 8 //цикл 8 раз
@loop2:
   //if boolean(Result and 1) then
   TEST AX, 1 //and с установкой флагов без изменения акамулятора
   JZ @m1 //Переход если 0
   SHR AX, 1 //Result := (Result shr 1) xor CRC_1
   XOR AX, CRC_1
   JMP @m2
@m1: // Result := Result shr 1;
   SHR AX, 1
@m2:
   LOOP @loop2
   INC     ESI                // Организуем т.о
   CMP     ESI, dword ptr len // цикл по буферу
   JB      @loop1              // --------------
   //в AX -  результат
   //
   pop ESI
end;
vvvch вне форума Ответить с цитированием
Старый 11.03.2013, 18:42   #5
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Вообще-то профайлер может ответить на вопрос "Где расходуется большая часть процессорного времени", но никак не на вопрос "стоит ли оптимизировать".

А на вопрос "стоит ли оптимизировать" отвечать можно либо путем измерения времени выполнения всего кода (нужно решить, какова максимально допустимая величина, и лежит ли измеренное значение в допустимых пределах) либо путем экспертной оценки (по ощущению - тормозит/не тормозит).
s-andriano вне форума Ответить с цитированием
Старый 12.03.2013, 06:47   #6
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

вообще даже асм не оптимален
Код:
   MOV ECX, 8 //цикл 8 раз
@loop2:
   SHR AX, 1  // в CF выдвинутый бит его и проверяем jnc
   JNC @m1  //проверка if boolean(Result and 1) then
   XOR AX, CRC_1
@m1:
   LOOP @loop2
никогда не делай cx=8 при использовании лупа т.к. в верхней части может быть мусор и залупнется надолго
Не стесняемся, плюсуем!

Последний раз редактировалось Slym; 12.03.2013 в 06:51.
Slym вне форума Ответить с цитированием
Старый 12.03.2013, 17:26   #7
vvvch
 
Регистрация: 11.03.2013
Сообщений: 5
По умолчанию

Цитата:
Сообщение от Slym Посмотреть сообщение
вообще даже асм не оптимален
Код:
   MOV ECX, 8 //цикл 8 раз
@loop2:
   SHR AX, 1  // в CF выдвинутый бит его и проверяем jnc
   JNC @m1  //проверка if boolean(Result and 1) then
   XOR AX, CRC_1
@m1:
   LOOP @loop2
никогда не делай cx=8 при использовании лупа т.к. в верхней части может быть мусор и залупнется надолго
Вообще-то это не ASM "виноват", это я плохо сделал (не как положено)... Спасибо, что заметили ошибку.
vvvch вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Профилирование RISagitov Microsoft Office Excel 6 25.09.2012 18:01
Профилирование (Измерение времени работы программы) megakatapuz Общие вопросы C/C++ 0 06.01.2010 23:04
Профилирование лопастей центробежных рабочих колёс Styu Общие вопросы Delphi 3 24.07.2007 13:56