|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
Помогите пожалуйста с профилированием
Я не большой специалист в программировании и много не знаю. Сделал две функции (метода) одна на паскале, другая на ассемблере. Они почти одинаковые, делают одно и то-же (вычисляют контрольную сумму (С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). Файл я приложил. Очень прошу - помогите. |
#2
|
||||
|
||||
Лучше не заморачиваться, например если ф-ю на ассемблере придется перепиливать под х64 - будет гемор, а которая на паскале - нет.
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#3
|
||||
|
||||
А почему код (асемблерный) должен отличаться для 32 и 64 разрядной версии? Вроде те регистры что 32 разрядные и там будут так-же работать. Правда как там осуществляется адресация памяти (разница) я не знаю. Но в данном случае код будет работать под WinXP Pro (32бит) Переход на 64разрядную пока не планируется.
|
#4
|
||||
|
||||
Для профилирования можно использовать AQTime, хотя ассемблер в данном случае большого прироста скорости не даст - не тот случай.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#5
|
|||
|
|||
Ну как вариант -
во первых - команда SHR вырабатывает флаг CF, если "выдвигаемый" разряд равен единице, тогда внутренний цикл можно подсократить - убрать команду сравнения и один переход Код:
@loop2: SHR AX, 1 JNB @m2 XOR AX, CRC_1 @m2: LOOP @loop2 Во вторых - этот внутренний цикл можно развернуть - просто переписать восемь раз. Тогда уберётся команда LOOP и освободится регистр ECX. Ну и счётчик внешнего цикла тоже лучше сделать в регистре. |
#6
|
||||
|
||||
Цитата:
Огромное СПАСИБО!!! Я не очень хорошо знаю ассемлер и долго с этим мучился (пытался подсократить). СПАСИБО! |
#7
|
||||
|
||||
Цитата:
Код:
INC ESI // Организуем т.о CMP ESI, dword ptr len // цикл по буферу JB @loop1 // -------------- А ведь счётчик и сделан в ESI это только проверка с памятью. Или её (проверку) тоже в освободившийся ECX? |
#8
|
||||
|
||||
команда loop работает с регистром ecx.
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#9
|
||||
|
||||
Цитата:
Да, но приращение идёт max, ...,3,2,1 выход. А мне, для работы с буфером, нужно 0,1,2,3,..., max-1. |
#10
|
||||
|
||||
Ну так вычитать из каунта ecx-i
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#11
|
||||
|
||||
Цитата:
это как??? Приведите пожалуйста пример. На самом деле я тоже обдумывал эти варианты, но тут появлыются "лишние" комманды. Проще просто инкрементировать регистр и проверить (cmp) его, выйти если условие не выполняется. |
#12
|
||||
|
||||
Слушайте, зачем весь этот изврат с сокращением кода? Не так уж и критично если будет на паскале написана ф-я.
— Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#13
|
||||
|
||||
Цитата:
Это конечно правильно. Но... всё-таки интересно сократить. Хотя это уже не имеет практического значения. Чистый "изврат". Если надоело - бросьте. А я подумал вот о чём Код:
... xor ECX, ECX mov ECX, dword ptr len mov ESI, ECX ... @loop1: ... mov al, byte ptr [buf+ESI-ECX] //на самом деле не mov a xor ну не важно, принцып ... loop @loop1 ... Правда тут встаёт вопрос насколько мы съэкономим время при вычислении [buf+ESI-ECX]? Может быть кто знает? |
#14
|
||||
|
||||
Можно же замерять.
Забыл какая ф-я до наносекунд может посчитать промежуток, завтра на работе пороюсь - скину. Чето со спаркой с getsystemfrequency. Вспомнил, QueryPerformanceCounter и QueryPerformanceFrequency. — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию Последний раз редактировалось M.A.D.M.A.N., 11.03.2013 в 17:57. |
#15
|
||||
|
||||
Я бы делал как-то так:
Код:
push esi mov bx, CRC_st //bX - Result mov ecx, len mov esi, buf cld @loop1: lodsb xor bl, al mov edx, 8 //цикл 8 раз @loop2: shr bx, 1 jc @m2 xor bx, CRC_1 @m2: dec edx jnz @loop2 dec ecx Jnz @loop1 mov ax, bx pop esi Но в любом случае, inc и cmp надо было убирать любыми методами. Это самое медленное в коде. А вариант с Цитата:
Цитата:
jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 11.03.2013 в 18:31. |