Optimizing Memory Allocation in a Simple, but Long Function

Chris Angelico rosuav at gmail.com
Sun Apr 24 14:21:51 EDT 2016


On Mon, Apr 25, 2016 at 4:03 AM, Derek Klinge <schilke.60 at gmail.com> wrote:
> Ok, from the gmail web client:

Bouncing this back to the list, and removing quote markers for other
people's copy/paste convenience.

## Write a method to approximate Euler's Number using Euler's Method
import math

class EulersNumber():
    def __init__(self,n):
        self.eulerSteps = n
        self.e    = self.EulersMethod(self.eulerSteps)
    def linearApproximation(self,x,h,d): # f(x+h)=f(x)+h*f'(x)
        return x + h * d
    def EulersMethod(self, numberOfSteps): # Repeate linear
approximation over an even range
        e = 1                                                    # e**0 = 1
        for step in range(numberOfSteps):
            e = self.linearApproximation(e,1.0/numberOfSteps,e) # if
f(x)= e**x, f'(x)=f(x)
        return e


def EulerStepWithGuess(accuracy,guessForN):
    n = guessForN
    e = EulersNumber(n)
    while abs(e.e - math.e) > abs(accuracy):
        n +=1
        e = EulersNumber(n)
        print('n={} \te= {} \tdelta(e)={}'.format(n,e.e,abs(e.e - math.e)))
    return e


def EulersNumberToAccuracy(PowerOfTen):
    x = 1
    theGuess = 1
    thisE = EulersNumber(1)
    while x <= abs(PowerOfTen):
        thisE = EulerStepWithGuess(10**(-1*x),theGuess)
        theGuess = thisE.eulerSteps * 10
        x += 1
    return thisE


> To see an example of my problem try something like EulersNumberToAccuracy(-10)

Yep, I see it.

I invoked your script as "python3 -i euler.py" and then made that call
interactively. It quickly ran through the first few iterations, and
then had one CPU core saturated; but at no time did memory usage look
too bad. You may be correct in Python 2, though - it started using
about 4GB of RAM (not a problem to me - I had about 9GB available when
I started it), and then I halted it.

The Python 3 version has been running for a few minutes now.

n=135914023 e= 2.718281818459972 delta(e)=9.999073125044333e-09

'top' says:
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 7467 rosuav    20   0   32432   9072   4844 R 100.0  0.1   3:58.44 python3

In other words, it's saturating one CPU core ("%CPU 100.0"), but its
memory usage (VIRT/RES/SHR) is very low. At best, this process can be
blamed for 0.1% of memory.

Adding these lines to the top makes it behave differently in Python 2:

try: range = xrange
except NameError: pass

The Py3 behaviour won't change, but Py2 should now have the same kind
of benefit (the xrange object is an iterable that doesn't need a
concrete list of integers).

ChrisA



More information about the Python-list mailing list