Конференция "FreePascal" » Асм в FPC
 
  • Rouse_ © (15.02.17 13:58) [20]
    Умные люди тут говорят :)

    function TRegion.PtInRegion(x, y: integer): boolean;
    asm
     cmp x, self.rEX
     ja @@Out
     cmp x, self.rX
     jl @@Out
     cmp y, self.rEY
     ja @@Out
     cmp y, self.rY
     jl @@Out
     mov al, 01h
     jmp @@exit
    @@Out:
     xor al, al
    @@exit:
    end;
  • dmk © (15.02.17 14:10) [21]
    Не, не хочет никак.
    Может проблема в том, что это не класс, а record.
    type
     PRegion = ^TRegion;
     TRegion = record
       private
         rX: integer; //Позиция слева
         rY: integer; //Позиция сверху
         rEX: integer; //Позиция справа
         rEY: integer; //Позиция снизу
         rW: integer; //Ширина включая первую точку
         rH: integer; //Высота включая первую точку
         procedure SetWidth(W: integer);
         procedure SetHeight(H: integer);
         procedure SetEX(EX: integer);
         procedure SetEY(EY: integer);
         function GetRect: TRect;
         procedure SetRect(R: TRect);
       public
         property X: integer read rX write rX;
         property Y: integer read rY write rY;
         property EX: integer read rEX write SetEX;
         property EY: integer read rEY write SetEY;
         property W: integer read rW write SetWidth;
         property H: integer read rH write SetHeight;
         procedure OffsetRegion(dx, dy: integer);
         function PtInRegion(x, y: integer): boolean;
         procedure ClipX(var x: integer);
         procedure ClipY(var y: integer);
         function InRangeX(x: integer): boolean;
         function InRangeY(y: integer): boolean;
         function OutRangeX(x: integer): boolean;
         function OutRangeY(y: integer): boolean;
         function RegionInRegion(R: TRegion): boolean;
         procedure Clear;
         function Empty: boolean;
         procedure AddPoint(dX, dY: integer);
         property Rect: TRect read GetRect write SetRect;
         procedure SwapX;
         procedure SwapY;
         procedure NormalizeX;
         procedure NormalizeY;
         procedure NormalizeXY;
      end;


    Просто удобнее с записью чем с классом.
  • dmk © (15.02.17 14:13) [22]
    Сам он свой код так интерпретирует:

    0000000100042954 488b45e8                 mov    -0x18(%rbp),%rax
    0000000100042958 8b00                     mov    (%rax),%eax
    000000010004295A 3b45f8                   cmp    -0x8(%rbp),%eax
    000000010004295D 7f30                     jg     0x10004298f <PTINREGION+79>
    000000010004295F 488b45e8                 mov    -0x18(%rbp),%rax
    0000000100042963 8b4008                   mov    0x8(%rax),%eax
    0000000100042966 3b45f8                   cmp    -0x8(%rbp),%eax
    0000000100042969 7c24                     jl     0x10004298f <PTINREGION+79>
    000000010004296B 488b45e8                 mov    -0x18(%rbp),%rax
    000000010004296F 8b4004                   mov    0x4(%rax),%eax
    0000000100042972 3b45f0                   cmp    -0x10(%rbp),%eax
    0000000100042975 7f12                     jg     0x100042989 <PTINREGION+73>
    0000000100042977 488b45e8                 mov    -0x18(%rbp),%rax
    000000010004297B 8b400c                   mov    0xc(%rax),%eax
    000000010004297E 3b45f0                   cmp    -0x10(%rbp),%eax
    0000000100042981 7c06                     jl     0x100042989 <PTINREGION+73>
    0000000100042983 c645e001                 movb   $0x1,-0x20(%rbp)
    0000000100042987 eb0a                     jmp    0x100042993 <PTINREGION+83>
    0000000100042989 c645e000                 movb   $0x0,-0x20(%rbp)
    000000010004298D eb04                     jmp    0x100042993 <PTINREGION+83>
    000000010004298F c645e000                 movb   $0x0,-0x20(%rbp)
  • Rouse_ © (15.02.17 14:21) [23]
    Ну тут даже не знаю как помочь, раз ты не хочешь отладчик в руки брать.
  • dmk © (15.02.17 14:39) [24]
    Да уже разобрался. У него переменная self слетает после первой проверки.
    Если тупо rcx указать, то все в порядке.

    function TRegion.PtInRegion(x, y: integer): boolean;
    //if (x >= rX) and (x <= rEX) then result := (y >= rY) and (y <= rEY) else result := false;
    asm
     cmp x, [rcx + rEX]
     jg @@Out
     cmp x, [rcx + rX]
     jl @@Out
     cmp y, [rcx + rEY]
     jg @@Out
     cmp y, [rcx + rY]
     jl @@Out
     mov al, 01h
     jmp @@Ex

    @@Out:
     xor al, al

    @@Ex:
    end;
  • dmk © (15.02.17 14:40) [25]
    Работает раза в 2 быстрее чем код который генерит FPC или дельфи. Потому и нужен асм.
    Приятно все закрутилось. Шустрее :)
  • dmk © (15.02.17 14:41) [26]
    И спасибо умным людям :) Пришлось убрать ret.
  • Rouse_ © (15.02.17 15:03) [27]
    Это всегда пожалуйста ;)
  • NoUser © (15.02.17 15:47) [28]
    > Пришлось убрать ret.
    конечно, ты ж
    .noframe


    не пишешь.


    > Работает раза в 2 быстрее чем код который генерит FPC или
    > дельфи. Потому и нужен асм.

    Потому и нужен диз-асм!, чтобы 'подсказать' компилятору что тебе нужно или увидеть правильно ли он тебя 'понял'.

    А
    function TRec.Test(x,y:Integer):Boolean; inline;
    begin
    Result := ( (x >= a) and (x <= b) and (y >= c) and (y <= d) );
    end;

    будет быстрее твоего асм и даже с .noframe
  • dmk © (15.02.17 17:20) [29]
    >будет быстрее твоего асм
    Тут неверно.
    Генерит медленный код. 2 чтения из памяти + сравнение * 4
    против моих 4-х сравнений с памятью. У меня фпс в 2 раза поднимается почти с функцией на асм.
  • dmk © (15.02.17 17:22) [30]
    А за NoFrame спасибо! Еще быстре стала ;)
  • NoUser © (15.02.17 22:39) [31]
    > dmk ©   (15.02.17 17:20) [29]

    странно, у тебя x,y перед вызовом тоже читаются и call/ret ещё запись/чтение.
    ( длина кода, правда, в ~2 раза меньше - сравнение reg,[reg] и короткие переходы - нужно будет затестить )
  • dmk © (16.02.17 02:04) [32]
    >нужно будет затестить
    Уже: http://hostingkartinok.com/show-image.php?id=0fa7af40519ce173cc460d598dcbedad
    Проц i7-6950X 3 ГГц. (20 ядер).

    Функция A - на ассемблере.
    Функция Б - на Delphi.

    Почти в 2 раза ;)
  • dmk © (16.02.17 02:10) [33]
    Функция A
    function TRegion.PtInRegion(x, y: integer): boolean;
    asm
     cmp x, [rcx + rEX]
     jg @@Out
     cmp x, [rcx + rX]
     jl @@Out
     cmp y, [rcx + rEY]
     jg @@Out
     cmp y, [rcx + rY]
     jl @@Out
     mov al, 01h
     jmp @@Ex

    @@Out:
     xor al, al

    @@Ex:
    end;


    Функция Б
    function TRegion.PtInRegion2(x, y: integer): boolean;
    begin
     Result := (x >= rX) and (x <= rEX) and (y >= rY) and (y <= rEY);
    end;
  • NoUser © (16.02.17 16:19) [34]
    > Проц i7-6950X 3 ГГц. (20 ядер).
    ну-ну.

    Сделай простой тест (rdtsc) на один поток.
    У меня  Asm/Inline  ~ 19/15

    ~2х может быть только из-за ошибок в коде или логике.
  • dmk © (16.02.17 21:54) [35]
    у меня точный тест через READ TSC.
    Я все функции тестирую на нем.
  • dmk © (16.02.17 23:21) [36]
    >ну-ну.
    Дык многопоточная отрисовка у меня :) PaintStream фактически.
    Тут же выкладывал: http://pda.delphimaster.net/?id=1486644466&n=5
  • dmk © (17.02.17 14:21) [37]
    По поводу ну-ну. Если взглянете в фотошоп, то в последних версиях (у меня CC 2017) во многих-многих местах уже многопоточность или использование GPU. У меня по тестам, даже неоптимизированный код Delphi в 8-10 раз быстрее выполняется. В оптимизированной версии кода есть случаи свыше 100%. Предсказание работает.
  • invis © (17.02.17 16:45) [38]
    Речь о том, что тестировать лучше в одном потоке, иначе непонятно, как воспринимать эти твои "почти 2 раза" - делить на 10? Или на 12 с учётом гипертрединга?
    У меня в FPC быстрее паскалевский вариант со всеми оптимизациями и инлайном. Без инлайна примерно одинаково, несмотря даже на то, что компилятор генерирует более длинный asm-код.
  • dmk © (17.02.17 16:52) [39]
    >как воспринимать эти твои "почти 2 раза"
    Там по ссылке результат теста. Кроме того возмущения непонятны. Нравится паскалевский вариант - ради бога. Руки никто никому не выламывает слава богу :)
 
Конференция "FreePascal" » Асм в FPC
Есть новые Нет новых   [118667   +46][b:0][p:0.001]