[Python-ideas] Python Numbers as Human Concept Decimal System

Chris Angelico rosuav at gmail.com
Wed Mar 5 10:36:42 CET 2014


On Wed, Mar 5, 2014 at 6:34 PM, Mark H. Harris <harrismh777 at gmail.com> wrote:
> hi Chris,  good to hear from another Rexx programmer! Back in the day
> (during
> my 25 year tenure with IBM, I wrote thousands of scripts in Rexx for VM370
> systems, and OS/2.  I too still have OS/2 running.  whoohoo!
>
> Don't take the Rexx reference too much to heart, I just wanted folks to know
> where I got my influence on this thinking. Rexx was too slow... so was
> Decimal
> until 3.3, and then, boy has it taken off so-to-speak!

Yes, that's true. But I've just done some performance testing. REXX on
our OS/2 VM accounting server "Stanley" calculates 10000! in 14
seconds; Pike on the same hardware calculates 100000! in 4 seconds. (I
didn't bother calculating 100000! in REXX, didn't feel like waiting.)
In each case it was by this naive algorithm:

REXX: n=1; do i=1 to 10000; n=n*i; end
Pike: int n=1; for (int i=1;i<=100000;++i) n*=i;

Those were running on the same hardware, and going to a target an
order of magnitude higher took a fraction of the time. That's what
integer performance is like. (BTW, I set 'numeric digits' to something
just a bit more than the target. REXX was pretty fast if I left digits
low, and I could then look at the exponent to see what digits setting
I needed. In Pike's case, the int type supports arbitrary precision
anyway, so the net result is a fair comparison; I could write the
digits out to a file and get the exact same result.)

>From here on, I've switched computers to Sikorsky, who has more
languages and more power than Stanley has. Timings here aren't
technically comparable to the above ones, but they seem similar. I
guess VirtualBox is doing a decent job of staying out of the way. Pike
on Sikorsky:

> gauge {int n=1; for (int i=1;i<=100000;++i) n*=i;};
(3) Result: 3.394805453

Okay. Now, Python.

Python 3.4.0rc1+ (default:a124b981a7a3, Mar  3 2014, 01:30:30)
[GCC 4.7.2] on linux
>>> def fac(top):
    t=time.time()
    n=1
    for i in range(1,top+1):
        n*=i
    return time.time()-t
>>> fac(100000)
7.814447641372681

Roughly double Pike's time. (I suspect this may be largely because
Pike has an optimization for machine-word integers. The difference is
far starker if the algorithm used is less naive.) Now watch the result
of a switch of data type.

def fac_d_maxprec(top):
    from decimal import Decimal, getcontext, MAX_PREC
    getcontext().prec=MAX_PREC
    t=time.time()
    n=Decimal("1")
    for i in range(1,top+1):
        n*=i
    return time.time()-t

(Note that the multiplication is still with ints. Doing all the
multiplication with Decimals would mean a whole lot more calling of
the constructor, which wouldn't be a fair comparison. If all of Python
used Decimal, then range() would be returning Decimal.)

>>> fac_d_maxprec(100000)
20.71300506591797

I also wrote an alternative version of the above which pre-calculates
at low precision, then sets the precision to just enough, and
recalculates. The timings were statistically identical to the above.

So there you are: A three to one difference. That's pretty amazing,
actually - the fact that it's not *far far* worse is a tribute to the
folks who gave us this highly optimized decimal.Decimal
implementation! But it's still dramatically slower than integer
calculations, and as you can see from the Pike version, the integer
figures can be cut a long way too.

I'm not sure that I want to give that up.

> But, I'm not the least concerned for performance being a problem,
> because I have thoroughly tested decimal.Decimal and it flat screams, unlike
> our old friend Rexx.

Yes, that's true (although frankly, when I first met REXX on OS/2, it
screamed compared to doing the job myself in C - sure, I could do
integer calculations quicker in C, but if I wanted to go above the
size of a long - 1<<32 - that was pretty hard), but the screaming
isn't so impressive compared to a modern integer engine.

> PS  Have you considered the way things might have been if Palmisano
> had played ball with Bill Gates and Steve Ballmer back in the day... OS/2
> would rule, gnu/linux might never have been invented period, and you and
> I might not be having this conversation today!  ha!  Go Big Blue.

Hmm, I don't think so. Linux had a rather different purpose, back
then. But yeah, OS/2 was brilliant tech built in a hostile
environment... I'd like to see some of its best parts lifted onto a
Linux kernel, though (like the WorkPlace Shell - should be possible to
run that on top of X11). Alas, most of OS/2 now is in the "was great
in the 90s, but other things do the same job now" basket, and a
closed-source system that boasts little above a GNU/Linux stack isn't
really going to go anywhere much.

Still, it's hanging around. It's the best way I have for running
16-bit Windows programs, believe it or not. (And yes, I did try
running Pastel Accounting under Wine. Win-OS/2 still beats Wine
hands-down, probably because Wine developers don't see any reason to
bother with supporting anything so ancient.)

ChrisA


More information about the Python-ideas mailing list