How to make Python run as fast (or faster) than Julia

bartc bc at freeuk.com
Mon Feb 26 06:13:51 EST 2018


On 26/02/2018 09:22, Steven D'Aprano wrote:
> On Sun, 25 Feb 2018 21:19:19 -0800, Rick Johnson wrote:
> 
> 
>> I agree with your sarcasm. And that's why these types of auto
>> conversions should be optional. I agree that most times it's more
>> practical to let python handle the dirty details. But in some cases,
>> where you need to squeeze out a few more drops of speed juice, you won't
>> mind the extra trouble.
> 
> And that's where you call out to a library like numpy, or write a C
> extension, or use a tool like Numba or Cython to optimise your Python
> code to use native ints. (Numba is still a work in progress, but Cython
> is a mature working product.)
> 
> Or to put it another way... if you want machine ints in Python, the way
> you get them is something like:
> 
> from numba import jit
> 
> @jit
> def myfunction(): ...
> 
> 
> 
> The core language doesn't have to support these things when there is a
> healthy language ecosystem that can do it.

Below is the first draft of a Python port of a program to do with random 
numbers. (Ported from my language, which in turned ported it from a C 
program by George Marsaglia, the random number guy.)

However, running it quickly exhausts the memory in my machine. The 
reason is that Python unhelpfully widens all results to bignums as 
needed. The code relies on calculations being modulo 2^64.

Note that restricting integer ops to 64 bits probably still won't work, 
as I believe the numbers need to be unsigned.

------------------------------------------

Q=0
carry=36243678541
xcng=12367890123456
xs=521288629546311
indx=20632

def refill():
     global Q, carry, indx
     for i in range(20632):
         h = carry & 1
         z = ((Q[i]<<41)>>1)+((Q[i]<<39)>>1)+(carry>>1)
         carry = (Q[i]>>23)+(Q[i]>>25)+(z>>63)
         Q[i] = ~((z<<1)+h)
     indx=1
     return Q[0]

def start():
     global Q, carry, xcng, xs, indx
     Q=[0,]*20632

     for i in range(20632):

         xcng=6906969069 * xcng + 123

         xs ^= (xs<<13)
         xs ^= (xs>>17)
         xs ^= (xs<<43)

         Q[i] = xcng + xs

     N = 100000
     for i in range(N):
         if indx<20632:
             s = Q[indx]
             indx+=1
         else:
             s = refill()
         xcng=6906969069 * xcng + 123
         xs ^= (xs<<13)
         xs ^= (xs>>17)
         xs ^= (xs<<43)
         x = s+xcng+xs
     print ("Does x= 4013566000157423768")
     print ("     x=",x)

start()

------------------------------------------

(The code performs N iterations of a random number generator. You get 
the result expected, ie. x=401...768, when N is a billion.)

-- 
Bartc



More information about the Python-list mailing list