BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

PAS loop faster than BASM
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Language BASM
View previous topic :: View next topic  
Author Message
Gary
Guest





PostPosted: Fri May 13, 2005 10:17 pm    Post subject: PAS loop faster than BASM Reply with quote



I created a BASM function that searches through an array of integers for
a value. To my surprise, it benchmarks at about 10 times slower than
the equivalent PAS version. Why is it so slow?

{----------------------------------------------------------
Searches an array of integers (or pointers) for a value.
Returns the position of the value, or -1 if not found.

On entry, EAX will contain P, EDX will contain Value,
and ECX will contain Count.
-----------------------------------------------------------}
function ScanArray(const P : Pointer;
const Value : Integer;
const Count : Integer) : Integer;
asm
jcxz @@Done // check for Count=0

// The following MUST be done in this order,
// since the parameters are actually in registers.

push EDI // must preserve EDI
mov EDI, P
mov EAX, Value
mov EDX, Count // remember the count for later

repne scasd // search!
jnz @@NotFound // success?

mov EAX, EDX // get the original count
sub EAX, ECX // subtract the end count
dec EAX // subtract 1 more for origin 0

pop EDI
ret

@@NotFound:
mov EAX, -1 // not found
pop EDI

@@Done:
end;

{ Pascal version }

function ScanArrayPAS(const P : array of integer;
const Value : Integer;
const Count : Integer) : Integer;
var
i : integer;
begin
Result := -1;

for i := Count - 1 downto 0 do
if P[i] = Value then
begin
Result := i;
break;
end;

end;
Back to top
Rudy Velthuis [TeamB]
Guest





PostPosted: Fri May 13, 2005 10:38 pm    Post subject: Re: PAS loop faster than BASM Reply with quote



At 00:17:55, 14.05.2005, Gary wrote:

Quote:
I created a BASM function that searches through an array of integers
for a value. To my surprise, it benchmarks at about 10 times slower
than the equivalent PAS version. Why is it so slow?

Why don't you have a look at the code produced by the PurePascal loop in
the CPU window? <g>

--
Rudy Velthuis [TeamB]

"The most important job is not to be Governor, or First Lady in my
case." -- George W. Bush

Back to top
Martin James
Guest





PostPosted: Fri May 13, 2005 10:38 pm    Post subject: Re: PAS loop faster than BASM Reply with quote



Dunno. REPNZ SCASD should be plenty fast.

Why not look at the assembly in the Delphi CPU window, find out & tell us?

Rgds,
Martin :)



Back to top
Gary
Guest





PostPosted: Fri May 13, 2005 10:40 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

The code produced by the PAS function is big and ugly. I can't imagine
why it's faster. Is there a way to copy it to the clipboard from the
CPU window?

Rudy Velthuis [TeamB] wrote:
Quote:
At 00:17:55, 14.05.2005, Gary wrote:


I created a BASM function that searches through an array of integers
for a value. To my surprise, it benchmarks at about 10 times slower
than the equivalent PAS version. Why is it so slow?


Why don't you have a look at the code produced by the PurePascal loop in
the CPU window?

Back to top
Rudy Velthuis [TeamB]
Guest





PostPosted: Fri May 13, 2005 10:45 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

At 00:40:52, 14.05.2005, Gary wrote:

Quote:
The code produced by the PAS function is big and ugly. I can't imagine
why it's faster. Is there a way to copy it to the clipboard from the
CPU window?

Yes, but only line by line.
--
Rudy Velthuis [TeamB]

"No mention of God. They keep Him up their sleeves for as long as
they can, vicars do. They know it puts people off." -- Alan Bennett.

Back to top
Rudy Velthuis [TeamB]
Guest





PostPosted: Fri May 13, 2005 10:46 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

At 00:40:52, 14.05.2005, Gary wrote:

Quote:
The code produced by the PAS function is big and ugly. I can't imagine
why it's faster.

Probably because the looping part is faster?
--
Rudy Velthuis [TeamB]

"Everybody wants to go to heaven, but nobody wants to die."
-- Joe Louis.

Back to top
Gary
Guest





PostPosted: Fri May 13, 2005 10:59 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

Rudy Velthuis [TeamB] wrote:
Quote:
At 00:40:52, 14.05.2005, Gary wrote:


The code produced by the PAS function is big and ugly. I can't imagine
why it's faster.


Probably because the looping part is faster?

{ begin }
push ebp
mov ebp,esp
add esp,-$14
mov [ebp-$0c],ecx
mov [ebp-$08],edx
mov [ebp-$04],eax
{ Result := -1; }
mov [ebp-$10],$ffffffff
{for i := Count - 1 downto 0 do }
mov eax,[ebp+$08]
sub eax,$01
jno +$05
call @IntOver
cmp eax,$00
jl +$30
mov [ebp-$14],eax
{ if P[i] = Value then }
mov eax,[ebp-$14]
test eax,eax
jl +$05
cmp eax,[ebp-$08]
jle +$05
call @BoundErr
mov edx,[ebp-$04]
mov eax,[edx+eax*4]
cmp eax,[ebp-$0c]
jnz +$08
{ Result := i; }
mov eax,[ebp-$14]
mov [ebp-$10],eax
{ break; }
jmp +$09
{ end; }
dec dword ptr [ebp-$14]
{ for i := Count - 1 downto 0 do }
cmp dword ptr [ebp-$14],-$01
jnz -$2d
mov eax,[ebp-$10]
{ end; }
mov esp,ebp
pop ebp
ret $0004

Back to top
Pierre le Riche
Guest





PostPosted: Sat May 14, 2005 7:42 am    Post subject: Re: PAS loop faster than BASM Reply with quote

Hi Gary,

Quote:
a value. To my surprise, it benchmarks at about 10 times slower than the
equivalent PAS version. Why is it so slow?

It's because you're using repne scasd and jcxz. The string manipulation
instructions are quite slow on the modern CPUs and jcxz is slower than using
a "test ecx, ecx; jz xxxx". This will be faster:

function ScanArray(P: Pointer; Value, Count: Integer): Integer;
asm
{On entry: eax = P, edx = Value, ecx = Count}
@CompareLoop:
sub ecx, 1
js @NotFound
cmp [eax + ecx * 4], edx
jne @CompareLoop
mov eax, ecx
ret
@NotFound:
mov eax, -1
end;

Regards,
Pierre



Back to top
Pierre le Riche
Guest





PostPosted: Sat May 14, 2005 7:59 am    Post subject: Re: PAS loop faster than BASM Reply with quote

Hi Again,

You can make it even shorter if you change the order of parameters and
change the definition of the return value from "-1 if not found" to
"negative if the value is not found". The return value will be -1 for all 0
or positive values of ACount, but will be (ACount - 1) if ACount was
negative on entry. Here goes:

{Scans a list of integers starting at address AFirstItem for ASearchValue,
returning the index of item if it was found or < 0 if not}
function ScanArray(ACount, ASearchValue: Integer; AFirstItem: Pointer):
Integer;
asm
{On entry: eax = ACount, edx = ASearchValue, ecx = @AFirstItem}
@CompareLoop:
sub eax, 1
js @Done
cmp [ecx + eax * 4], edx
jne @CompareLoop
@Done:
end;

Regards,
Pierre


Back to top
Robert Houdart
Guest





PostPosted: Sat May 14, 2005 10:24 am    Post subject: Re: PAS loop faster than BASM Reply with quote

Quote:
function ScanArray(ACount, ASearchValue: Integer; AFirstItem: Pointer):
Integer;
asm
{On entry: eax = ACount, edx = ASearchValue, ecx = @AFirstItem}
@CompareLoop:
sub eax, 1
js @Done
cmp [ecx + eax * 4], edx
jne @CompareLoop
@Done:
end;

That's what I would call elegant code!

For very large arrays the "sentinel" approach can be useful: you start by
putting the value you're looking for at the end of the array.
That way you've got only one compare/conditional jump in the loop.

Robert



Back to top
Gary
Guest





PostPosted: Sat May 14, 2005 12:55 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

Wonderful, thank you!

I found that my original tests were not using truly random samples, and
since the ASM code searched forward through the array while the PAS
version searched backward through the array, that accounted for the huge
difference. When my samples were more random, the timings were closer,
but the PAS version was still faster. Your version is the fastest.

I wasn't aware that the string instructions were so slow.

Thanks!

....Gary
Back to top
Gary
Guest





PostPosted: Sat May 14, 2005 1:32 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

I'm finding that I have to check the count before calling the ASM
routine because passing the address of the first element generates an
exception if the array is empty. For example, the following will
generate an exception if MyArray has no elements:

Result := ScanArray(Length(MyArray), Value, @MyArray[0]);

So I find that I have to do this, even though ScanArray would safely
handle it:

if Length(MyArray) > 0 then
Result := ScanArray(Length(MyArray), Value, @MyArray[0])
else
Result := -1;

Is there a simpler way to accomplish this? Do I have to turn off range
checking?


Back to top
Lee_Nover
Guest





PostPosted: Sat May 14, 2005 2:09 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

Result := ScanArray(Length(MyArray), Value, @MyArray);
should work as well
Back to top
Gary
Guest





PostPosted: Sat May 14, 2005 2:13 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

Does that work with dynamic arrays, as well?

Lee_Nover wrote:
Quote:
Result := ScanArray(Length(MyArray), Value, @MyArray);
should work as well

Back to top
Pierre le Riche
Guest





PostPosted: Sat May 14, 2005 4:50 pm    Post subject: Re: PAS loop faster than BASM Reply with quote

Hi Gary,

Quote:
Does that work with dynamic arrays, as well?

The code you're looking for is:

Result := ScanArray(length(MyArray), Value, Pointer(MyArray))

Long string and dynamic array references are effectively pointers to the
first character or element, so typecasting it to a pointer will avoid the
range check error you get when using @MyArray[0] with a zero length array.

Regards,
Pierre



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Language BASM All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.