[comp.lang.smalltalk] Integer / Float arithmetic in ST80

hm279he@uni-duisburg.de (Heckes) (05/15/91)

	I am using ST80 from ParcPlace on 386PC under Windows. I plan
	to use the system for prototyping of numerical algorithems and    
	if we get ST80 for our IBM6000 I will surely use them. To get
	an impression of the speed in number crunching, I performed some
	benchmarks with variables from the classes *Integer, Float and 
	Double. As my PC is equipped with a coprocessor I expected class  
	Float and SmallInteger to perform similar. I was very surprised, 
	when it turned out that the simple integer arithmetic, like +,* 
	etc, was 10 times faster then the equivalent messages in class
	Float. After looking a while around in the source code, I find 
	that also both classes implement the messages as primitives, the 
	messages in class SmallInteger are handled somewhat different.
	The messages in SmallInteger are marked essential and seem to
	be called in a different way as other primitives. There is a thing
	named Special Byte Code Selector which, as I understand, is send
	to the Compiler to make execution faster. 
	My question is: Is it possible to make the Float messages perform
	as fast as the SmallInteger ones?

	Dirk


	dirk@hal9000.uni-duisburg.de
	Dirk Talkenberger
	Physics Department / Theoretical Low Temperature Physics
 

pkr@media03.UUCP (Peter Kriens) (05/21/91)

hm279he@uni-duisburg.de (Heckes) writes:

        My question is: Is it possible to make the Float messages perform
        as fast as the SmallInteger ones?

I don't think that you can make the floats as fasts as Integers, even if you
would have zero calculate time. The point is, is that SmallIntegers are a very
special breed of objects. In most Smalltalks, the object pointer domain is
divided in two ranges. A bit in this pointer specifies if it is a pointer
or an Integer. This means that there is no garbage collection on instances of
the class integer. The pointer is the instance. Because a float uses from 4 to
10 bytes of memory, you will create a lot of very small objects, and they
need to be created and garbage collected, so that is where your time goes.

	Peter Kriens

johnson@cs.uiuc.EDU (Ralph Johnson) (05/22/91)

Peter Kriens explained why Floats are a lot slower in Smalltalk
than Integers.  Although he was technically correct, he was
sociologically wrong.  The reasons that Floats are slow in
Smalltalk are because they aren't use much; they aren't used
much because they are slow.  The venders optimize their systems
for the common cases, and the common cases are Integers.

It is possible to do the same tricks with Floats as are done
with Integers.  With enough effort, I bet we could make Floats
as fast as Integers.  I wish that would happen, because
Smalltalk would make a very good environment for scientific
computing if it were only faster at floating point arithmetic.

Given an appropriate financial incentive, I would be willing 
to prove my point.

Ralph Johnson -- University of Illinois at Urbana-Champaign

klimas@iccgcc.decnet.ab.com (05/30/91)

In article <1991May21.222216.5429@m.cs.uiuc.edu>, johnson@cs.uiuc.EDU (Ralph Johnson) writes:
> Peter Kriens explained why Floats are a lot slower in Smalltalk
> than Integers.  Although he was technically correct, he was
> sociologically wrong.  The reasons that Floats are slow in
> Smalltalk are because they aren't use much; they aren't used
> much because they are slow.  The venders optimize their systems
> for the common cases, and the common cases are Integers.
> 
> It is possible to do the same tricks with Floats as are done
> with Integers.  With enough effort, I bet we could make Floats
> as fast as Integers.  I wish that would happen, because
> Smalltalk would make a very good environment for scientific
> computing if it were only faster at floating point arithmetic.

Some information that may be of relevance to this topic and an earlier
discussion about the limited speed gains from rewritng Smalltalk into
C may be seen from the following benchmarks that I have started to collect.
All of the statistics were gathered on the same machine (a 33Mhz 386PC with a
math coprocessor)

		2499 Savage Test	1000 times recursive fibonacci of 12

DOS MS C 5.1		490msec			1320msec
ST/V-PM			530			2000
ST/V286			770			3630
ST/V-Windows		900			4290
ST-80 Windows	       1400			1593

A couple of additional facts; 

	ST-80 is 32 bit, while all of the other
	implementations are still 16 bit.

	the 2499 Savage test is
	1 to: 2499 by: 1 do: [:a| a:= (a*a) sqrt ln exp arcTan tan + 1]

The intersting analyses/corroborations of previous net statements
in these numbers are:

	Floating point can be handled almost as efficiently with Smalltalk
	as with C.

	Smalltalk is not much slower than C, which is already an accepted
	language for many numerically intensive applications and hence should
	make an excellent environment for simulations.

boehm@parc.xerox.com (Hans Boehm) (05/31/91)

klimas@iccgcc.decnet.ab.com writes:
>All of the statistics were gathered on the same machine (a 33Mhz 386PC with a
>math coprocessor)

>		2499 Savage Test	1000 times recursive fibonacci of 12

>DOS MS C 5.1		490msec			1320msec
>ST/V-PM			530			2000
>ST/V286			770			3630
>ST/V-Windows		900			4290
>ST-80 Windows	       1400			1593

>A couple of additional facts; 

>	ST-80 is 32 bit, while all of the other
>	implementations are still 16 bit.

>	the 2499 Savage test is
>	1 to: 2499 by: 1 do: [:a| a:= (a*a) sqrt ln exp arcTan tan + 1]

>The intersting analyses/corroborations of previous net statements
>in these numbers are:

>	Floating point can be handled almost as efficiently with Smalltalk
>	as with C.

>	Smalltalk is not much slower than C, which is already an accepted
>	language for many numerically intensive applications and hence should
>	make an excellent environment for simulations.

My conclusions from these numbers are:
1. Smalltalk is not much slower than C on programs whose execution time is
completely dominated by time spent executing very slow floating point
instructions or library calls (such as ln and tan).

2. Smalltalk can execute recursive procedure calls/method invocations almost
as fast as C under some simple circumstances.  This may mean something on
a '386.  I don't know.  If the numbers came from a Vax, it would mean that
the Smalltalk implementations didn't stick to the standard calling convention,
where the C implementation did.

This also doesn't address the question of whether the Smalltalk compilation
techniques scale to large programs.

Hans
(boehm@xerox.com)

CWatts@BNR.CA (Carl Watts) (05/31/91)

Dear klimas@iccgcc.decnet.ab.com,

Theres a big problem I think with your "2499 Savage Test" code for Smalltalk.  You expressed it as:
	1 to: 2499 by: 1 do: [:a | a:= (a*a) sqrt ln exp arcTan tan + 1]

First of all, in Smalltalk-80 2.5 this loop will only execute about 1250 times, not 2499 times.  The "a" is being incremented twice each time through the loop.  Once by the to:by:do: and once by the "+1".

Also the assignment "a:=" inside the loop should have no affect at all to the next invocation of the loop.  Unfortunately because of a bug in the Compilers inlining of the code for the method to:do:, it actually does have an affect in Smalltalk-80 2.5, I'm not sure if it does in Smalltalk V.

In Smalltalk-80 4.0, this expression won't even execute at all, you will get an error from the Compiler telling you that it is illegal to assign to an argument like that.

If this bug in Smalltalk 2.5 was not present then the loop would execute 2499 times but then the "a :=" would have no effect whatsover.

Anyway, I think what you really want is:

| a |
a := 1.
2499 timesRepeat: [
	a := (a*a) sqrt ln exp arcTan tan + 1]

if you are interested in the final value of "a" after the loop is finished.
FYI:  The final value of a in this expression (for Smalltalk-80 2.5) is 2477.24 not 2500 as infinite precision would give you.

Since you're Smalltalk timings for this benchmark are off by 50% (approx) you should redo your benchmarks and publish them again.

CWatts@BNR.CA (Carl Watts) (06/06/91)

In regards to the "Re: Integer / Float arithmetic in ST80 (Some benchmarks)" message I posted a while ago, "Ed Klimas" sent me a response through normal mail.  Because the message and my response are of general userfulness to Smalltalkers, I'll post my answer here (hope you don't mind Ed?)

You said in your message "I also don't see how the execution is limited to 1250 times, an interval of 1 to 2499 IS presented to the block under all of the SMalltalks that I tested."

If you execute the following in Smalltalk-80 v2.5 (or earlier probably) (it won't execute at all in Smalltalk-80 v4.0):

| c | c := 0.
1 to: 2499 by: 1 do: [:a |
	a := (a*a) sqrt ln exp arcTan tan + 1.
	c := c + 1]

you will see that the final value of "c" is 1251 NOT 2500.  This shows the loop only executed half the number of times it was intended to.

I'm not sure also that readers of the above code would realize (as my friend Joe May didn't) that:
	a := (a*a) sqrt ln exp arcTan tan + 1
is the same as (given precise arithmetic):
	a := a + 1
This is important because it is easier to see the problem with:
	1 to: 2499 by: 1 do: [:a | a := a + 1]
since you don't get thrown off by the trig functions.

The Smalltalk-80 v2.5 compiler compiles the to:by:do: message inline.  This message doesn't actually get sent, instead the code for it is compiled right into the method that uses it.  The comment for the method Integer>to:by:do: mentions this.

This would be fine if it weren't for the fact that a certain optimization is done by the compiler when it does this.  This optimization has a bug in it in that it allows assignment to the blocks local variables ("a" in your case) to have an effect on the next invocation of the block.

This means your "a := ... + 1" DOES IN FACT increment "a" for the next invocation of the loop.  But the to:by:do:'s job is also to increment the parameter to the block each time through the loop.  So because of this inline bug, the "a" gets incremented TWICE through the loop.  This is why it only executes 1250 times instead of 2500 times.

Anway, even in other Smalltalk's which don't have this bug, the Savage Test code you used is still improperly formed.  In these Smalltalk's the "by: 1" part, the "a:=" part, and the "+1" part of the loop shouldn't be there.  The "by: 1" is unnecessary, the "a :=" is meaningless (or illegal), and the "+1" is improper since the reason you are using to:by:do: is because it increments the parameter to the block.

The other code you gave (if you want to answer the final value of "a") is also wrong:
| a |
1 to: 2499 by: 1 do: [:a| a:= (a*a) sqrt ln exp arcTan tan +1]
^a

In a properly functioning Smalltalk this either: a) wouldn't execute at all because its illegal to assign to a parameter to a block or: b) would answer "nil" since the "a" inside the loop is a different "a" from the one outside the loop.

In some Smalltalk's this expression would happen to work ONLY because of TWO known "bugs" in the these Smalltalks.  The first is the aforementioned bug in the Compiler's inlineing of the to:by:do: statement.  The second bug is the fact that some Smalltalk's (like older Smalltalk-80's) used method temp vars for block temp vars.  In any properly functioning Smalltalk, that expression would never work right.

You definitely want:
| a |
a := 1.
2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1]

I found it very interesting that you reported that Smalltalk/V answered the precise answer "2500" for the final value of "a" with the code you gave above.  This shows that either Smalltalk/V is using incredibly precise trig arithmetic OR that you got the answer "2500" only because of the aforementioned bugs in the Smalltalk implementation.  Only because of these bugs could your expression happen to have given you the right answer.

I suspect if you redo your benchmark test using my version of this Savage Benchmark, you will find:

a)  Smalltalk/V does not have incredibly precise trig arithmetic, it was just a bizarre coincidence that bugs in your expression made use of bugs in the Smalltalk to give you the impression that it did.

b)  The times you gave for Smalltalk-80 v2.5 were off by about 50% because the loop only executed half the expected number of times.

Please get back to us about Smalltalk/V's precision.  I would be very interested to find out how Smalltalk/V fares in precision to Smalltalk-80 for a properly formulated expression of this benchmark.

objtch@extro.ucc.su.OZ.AU (Peter Goodall) (06/07/91)

CWatts@BNR.CA (Carl Watts) writes:

And thanks very much for the discussion.

>In regards to the "Re: Integer / Float arithmetic in ST80 (Some benchmarks)" message I posted a while ago, "Ed Klimas" sent me a response through normal mail.  Because the message and my response are of general userfulness to Smalltalkers, I'll post my answer here (hope you don't mind Ed?)

[stuff deleted]

>You definitely want:
>| a |
>a := 1.
>2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1]

>I found it very interesting that you reported that Smalltalk/V answered the precise answer "2500" for the final value of "a" with the code you gave above.  This shows that either Smalltalk/V is using incredibly precise trig arithmetic OR that you got the answer "2500" only because of the aforementioned bugs in the Smalltalk implementation.  Only because of these bugs could your expression happen to have given you the right answer.

>I suspect if you redo your benchmark test using my version of this Savage Benchmark, you will find:

>a)  Smalltalk/V does not have incredibly precise trig arithmetic, it was just a bizarre coincidence that bugs in your expression made use of bugs in the Smalltalk to give you the impression that it did.

>b)  The times you gave for Smalltalk-80 v2.5 were off by about 50% because the loop only executed half the expected number of times.

>Please get back to us about Smalltalk/V's precision.  I would be very interested to find out how Smalltalk/V fares in precision to Smalltalk-80 for a properly formulated expression of this benchmark.
 
Here are some interesting results using Smalltalk/V Windows:

	 |a|
	 1 to: 9 do: [ :a | a := a + 100].
	 ^a

	gives the answer: 102

         | a |
         a := 1.
         2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1].
	 ^a
	 answers:   2500.0

I executed the first expression in the debugger and was reminded that I had
seen the variable 'to:' materialize in this situation before. An artifact
of optimisation?

Note that I am not using the maths processor, and therefore the aritmetic
routines should be from the floating point emulation DLL, which has C
source code which from memory is the usual arithmetic out of the Microsoft
C library.

I also executed the following to elminate the looping, and just see the
arithmetic results:

	| a |
	a := 9999.
	a := (a*a) sqrt ln exp arcTan tan + 1.
	^a

	answers:  10000.0

Comments please! I am amazed at the very first of my results.





-- 
Peter Goodall - Smalltalk Systems Consultant - objtch@extro.ucc.su.oz.au
      ObjecTech Pty. Ltd. - Software Tools, Training, and Advice
162 Burns Bay Rd, LANE COVE, NSW, AUSTRALIA. - Phone/Fax: +61 2 418-7433

klimas@iccgcc.decnet.ab.com (06/12/91)

In article <1991Jun5.185120.8104@bqnes74.bnr.ca>, CWatts@BNR.CA (Carl Watts) writes:
Because of some sort of problem with Carl's mail reader I have reformatted
his posting and inserted a few observations of my own on a subject that has
now gotten far away from my original short posting about the potential 
suitability of Smalltalk for numerical computations.  I was not convinced that 
this thread was worth much net bandwidth and hence I was trying to keep it 
offline however since Carl brought this to the public forum with so many 
issues, I thought that I would try to answer what little I knew about the 
subject.
 
> In regards to the "Re: Integer / Float arithmetic in ST80 (Some benchmarks)" 
> message I posted a while ago, "Ed Klimas" sent me a response through normal 
> mail.  Because the message and my response are of general userfulness to 
> Smalltalkers, I'll post my answer here (hope you don't mind Ed?)
I don't, but all of our mail readers do <GRIN>!

> 
> You said in your message "I also don't see how the execution is limited to 
> 1250 times, an interval of 1 to 2499 IS presented to the block under all of 
> the SMalltalks that I tested."
> 
> If you execute the following in Smalltalk-80 v2.5 (or earlier probably) 
> (it won't execute at all in Smalltalk-80 v4.0):
> 
> | c | c := 0.
> 1 to: 2499 by: 1 do: [:a |
> 	a := (a*a) sqrt ln exp arcTan tan + 1.
> 	c := c + 1]
> you will see that the final value of "c" is 1251 NOT 2500.  This shows the 
> loop only executed half the number of times it was intended to.
Under Digitalk's Smalltalk this does execute properly with C having the
final correct value of 2499

> 
> I'm not sure also that readers of the above code would realize (as my friend 
> Joe May didn't) that:
> 	a := (a*a) sqrt ln exp arcTan tan + 1
> is the same as (given precise arithmetic):
> 	a := a + 1
> This is important because it is easier to see the problem with:
> 	1 to: 2499 by: 1 do: [:a | a := a + 1]
> since you don't get thrown off by the trig functions.
> 
> The Smalltalk-80 v2.5 compiler compiles the to:by:do: message inline.  This 
> message doesn't actually get sent, instead the code for it is compiled right 
> into the method that uses it.  The comment for the method Integer>to:by:do: 
> mentions this.
> 
> This would be fine if it weren't for the fact that a certain optimization is 
> done by the compiler when it does this.  This optimization has a bug in it 
> in that it allows assignment to the blocks local variables ("a" in your case)
> to have an effect on the next invocation of the block.
> 
> This means your "a := ... + 1" DOES IN FACT increment "a" for the next 
> invocation of the loop.  But the to:by:do:'s job is also to increment the 
> parameter to the block each time through the loop.  So because of this 
> inline bug, the "a" gets incremented TWICE through the loop.  This is why it 
> only executes 1250 times instead of 2500 times.
Interesting theory, but how does it explain the fact that the answers come
out correctly?
 
> Anway, even in other Smalltalk's which don't have this bug, the Savage Test 
> code you used is still improperly formed.  In these Smalltalk's the "by: 1" 
> part, the "a:=" part, and the "+1" part of the loop shouldn't be there.  
> The "by: 1" is unnecessary, the "a :=" is meaningless (or illegal), and 
> the "+1" is improper since the reason you are using to:by:do: is because it 
> increments the parameter to the block.
A rebuttal on this one!  The by: 1 IS necessary to avoid a potential bug in
some of the older Digitalk virtual machines (they also razzle dazzled
themselves with some optimizations <GRIN>).  There is nothing in the Blue Book 
or elsewhere that I am familiar with that says that the a:= in a block is an 
illegal expression, although PPLace has made changes to ST-80's handling of 
blocks now.  I suspect that this probably would cause significant grief from
Digitalk's much larger customer base if they also tried to follow PPlace 
on this as they might have to change their existing code.

> The other code you gave (if you want to answer the final value of "a") is 
> also wrong:
> | a |
> 1 to: 2499 by: 1 do: [:a| a:= (a*a) sqrt ln exp arcTan tan +1]
> ^a
> 
> In a properly functioning Smalltalk this either: a) wouldn't execute at all 
> because its illegal to assign to a parameter to a block or: b) would answer 
> "nil" since the "a" inside the loop is a different "a" from the one outside 
> the loop.
Depends which dialect one considers properly functioning <GRIN>!
It functions just nicely on all of the Digitalk Smalltalk's and I don't 
believe that it was illegal to assign a parameter inside a block when the 
Blue Book was written.  However to acknowledge that ST-80 may complain about 
the scoping, one can get identical results with
| b |
1 to: 2499 by: 1 do: [:a| b:= (a*a) sqrt ln exp arcTan tan + 1]
^b

 
> In some Smalltalk's this expression would happen to work ONLY because of 
> TWO known "bugs" in the these Smalltalks.  The first is the aforementioned 
> bug in the Compiler's inlineing of the to:by:do: statement.  The second bug 
> is the fact that some Smalltalk's (like older Smalltalk-80's) used method 
> temp vars for block temp vars.  In any properly functioning Smalltalk, that 
> expression would never work right.
What do we do if I tell you that Digitalk's Smalltalk does do it, tell them to
make it so it doesn't?

> You definitely want:
> | a |
> a := 1.
> 2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1]
My copy of ST-80 for Windows won't handle this expression but Digitalk does!
Give me an expression that you've checked first and I'll be glad to rerun it
on the other dialects.

> 
> I found it very interesting that you reported that Smalltalk/V answered the 
> precise answer "2500" for the final value of "a" with the code you gave 
> above.  This shows that either Smalltalk/V is using incredibly precise trig 
> arithmetic OR that you got the answer "2500" only because of the 
> aforementioned bugs in the Smalltalk implementation.  Only because of these 
> bugs could your expression happen to have given you the right answer.
Not so.  Digitalk's answers are exact!  As I mentioned in my private email
to you on this subject, I verified that there was no monkey business going
on by eliminating one of the transcendental functions that would have
rebalanced the answer.  As expected the answer changes, with changes to the
equation.  As far as I can tell there is no reason to be suspect of the 
answers that Digitalk's Smalltalk produces.

> 
> I suspect if you redo your benchmark test using my version of this Savage 
> Benchmark, you will find:
> 
> a)  Smalltalk/V does not have incredibly precise trig arithmetic, it was 
> just a bizarre coincidence that bugs in your expression made use of bugs 
> in the Smalltalk to give you the impression that it did.
This theory has been disproven using the fact that your version of the
benchmark on Digitalk's Smalltalk also gives the correct answer exactly.

> 
> b)  The times you gave for Smalltalk-80 v2.5 were off by about 50% because 
> the loop only executed half the expected number of times.
I don't believe this is true because the answer under ST-80 comes
out very closely to the correct one with just a little residue (it
was 2500.11).  One thing to note is that when doing the actual timing
tests, I did not display the answer, because it was not germain to what was
being measured.

> 
> Please get back to us about Smalltalk/V's precision.  I would be very 
> interested to find out how Smalltalk/V fares in precision to Smalltalk-80 
> for a properly formulated expression of this benchmark.
So far /V looks right on, but give me your properly formulated expression via
email (after you fix your mail reader <GRIN>) and I'll be happy to discuss 
the results offline, further.

jaz@icd.ab.com (Jack A. Zucker) (06/12/91)

In article <1991Jun11.175540.4836@iccgcc.decnet.ab.com>,
klimas@iccgcc.decnet.ab.com writes:
|> In article <1991Jun5.185120.8104@bqnes74.bnr.ca>, CWatts@BNR.CA (Carl
Watts) writes:
|> 
|> > You definitely want:
|> > | a |
|> > a := 1.
|> > 2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1]
|> My copy of ST-80 for Windows won't handle this expression but Digitalk does!
|> Give me an expression that you've checked first and I'll be glad to rerun it
|> on the other dialects.
|> 

This expression worked just fine on my copy of ST-80 for Windows.

| Jack A Zucker         {cwjcc,pyramid,decvax,uunet}!jaz@icd.ab.com |
| Allen-Bradley Company, Inc. or                     ICCGCC::ZUCKER |
| 747 Alpha Drive                                                   |
| Highland Hts., OH 44143 Phone(216) 646-4668   FAX: (216) 646-4484 |