-
Умные люди тут говорят :)
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;
-
Не, не хочет никак. Может проблема в том, что это не класс, а 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;
Просто удобнее с записью чем с классом.
-
Сам он свой код так интерпретирует:
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)
-
Ну тут даже не знаю как помочь, раз ты не хочешь отладчик в руки брать.
-
Да уже разобрался. У него переменная 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;
-
Работает раза в 2 быстрее чем код который генерит FPC или дельфи. Потому и нужен асм. Приятно все закрутилось. Шустрее :)
-
И спасибо умным людям :) Пришлось убрать ret.
-
Это всегда пожалуйста ;)
-
> Пришлось убрать 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
-
>будет быстрее твоего асм Тут неверно. Генерит медленный код. 2 чтения из памяти + сравнение * 4 против моих 4-х сравнений с памятью. У меня фпс в 2 раза поднимается почти с функцией на асм.
-
А за NoFrame спасибо! Еще быстре стала ;)
-
> dmk © (15.02.17 17:20) [29]
странно, у тебя x,y перед вызовом тоже читаются и call/ret ещё запись/чтение. ( длина кода, правда, в ~2 раза меньше - сравнение reg,[reg] и короткие переходы - нужно будет затестить )
-
-
Функция 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;
-
> Проц i7-6950X 3 ГГц. (20 ядер). ну-ну.
Сделай простой тест (rdtsc) на один поток. У меня Asm/Inline ~ 19/15
~2х может быть только из-за ошибок в коде или логике.
-
у меня точный тест через READ TSC. Я все функции тестирую на нем.
-
-
По поводу ну-ну. Если взглянете в фотошоп, то в последних версиях (у меня CC 2017) во многих-многих местах уже многопоточность или использование GPU. У меня по тестам, даже неоптимизированный код Delphi в 8-10 раз быстрее выполняется. В оптимизированной версии кода есть случаи свыше 100%. Предсказание работает.
-
Речь о том, что тестировать лучше в одном потоке, иначе непонятно, как воспринимать эти твои "почти 2 раза" - делить на 10? Или на 12 с учётом гипертрединга? У меня в FPC быстрее паскалевский вариант со всеми оптимизациями и инлайном. Без инлайна примерно одинаково, несмотря даже на то, что компилятор генерирует более длинный asm-код.
-
>как воспринимать эти твои "почти 2 раза" Там по ссылке результат теста. Кроме того возмущения непонятны. Нравится паскалевский вариант - ради бога. Руки никто никому не выламывает слава богу :)
|