memory error

65 views
Skip to first unread message

klmn

unread,
Sep 3, 2010, 12:08:14 PM9/3/10
to sympy
Dear all,

I am trying to implement various schemes for storing Gaunt
coefficients (integrals of 3 spherical harmonics) calculated
symbolically. Ondrej, I remember you offered me help for this, now I
have to ask for it.

It appears that at moderately big indices, already at l_max~30, the
memory is all eaten up. I tried to force garbage collection, without
success. Interestingly, if I repeatedly calculate just one Gaunt
coefficient for a fixed set of indices, there is no memory problem
(commented out in the script below)…

There is no memory leak per se. When I exit from Python, the memory is
fully recovered. It seems that the garbage is not collected during the
calculations, even when asked, untill it occupies the whole memory.

Below I attach a test module. Sorry for the long post: I don’t see a
way how I could attach it as a file (I am using a web form).

Can you recommend me a memory saving approach?

Best regards,
Konstantin

****************************************
import numpy as np
import sympy
import tables
#import gc
import time

factorials=[sympy.Integer(1)]

def get_factorials(nn):
""" Precalculated factorials """
if nn >= len(factorials):
for ii in range(len(factorials), nn + 1):
factorials.append(factorials[ii - 1] * ii)
return factorials[:(nn + 1)]

def zero_gaunt_l(l_1, l_2, l_3):
"""
Checks l indices for giving an even sum and fulfilling the
triangle realtion.
"""
if np.mod(l_1 + l_2 + l_3, 2) != 0: return True
if l_1 + l_2 - l_3 < 0: return True
if l_1 - l_2 + l_3 < 0: return True
if -l_1 + l_2 + l_3 < 0: return True
return False

def zero_gaunt_m(l_1, l_2, l_3, m_1, m_2, m_3):
"""
Checks m indices for giving 0 sum and being limited by l's
"""
if (m_1 + m_2 + m_3) != 0: return True
if (abs(m_1) > l_1) or (abs(m_2) > l_2) or (abs(m_3) > l_3):
return True
return False

def gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None, include4Pi=True):
"""
Check validity of the indices and calculate the Gaunt coefficient.
"""
if type(l_1) != type(l_2) != type(l_3) != type(1):
raise ValueError("l values must be integer")
if type(m_1) != type(m_2) != type(m_3) != type(1):
raise ValueError("m values must be integer")

if zero_gaunt_l(l_1, l_2, l_3): return 0
if zero_gaunt_m(l_1, l_2, l_3, m_1, m_2, m_3): return 0

return calc_gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec, include4Pi)

def calc_gaunt(l_1, l_2, l_3, m_1, m_2, m_3, prec=None,
include4Pi=True):
"""
Calculate the Gaunt coefficient.
"""
a1 = l_1 + l_2 - l_3
a2 = l_1 - l_2 + l_3
a3 = -l_1 + l_2 + l_3

bigL = (l_1 + l_2 + l_3) / 2
a4 = -l_3 + l_1 + m_2
a5 = -l_3 + l_2 - m_1
imin = max(a4, a5, 0)
a6 = l_2 + m_2
a7 = l_1 - m_1
imax = min(a6, a7, a1)

maxFactorial = max(l_1 + l_2 + l_3, imax) + 1
get_factorials(maxFactorial)

trySeparate = True # test whether the factors under sqrt must be
kept
if trySeparate:
prefac1 = sympy.sqrt(2 * l_1 + 1) *\
sympy.sqrt(2 * l_2 + 1) *\
sympy.sqrt(2 * l_3 + 1) *\
sympy.sqrt(factorials[a7]) *\
sympy.sqrt(factorials[l_1 + m_1]) *\
sympy.sqrt(factorials[l_2 - m_2]) *\
sympy.sqrt(factorials[a6]) *\
sympy.sqrt(factorials[l_3 - m_3]) *\
sympy.sqrt(factorials[l_3 + m_3])
else:
prefac1 = sympy.sqrt((2 * l_1 + 1) * (2 * l_2 + 1) * (2 * l_3
+ 1) *\
factorials[a7] *\
factorials[l_1 + m_1] *\
factorials[l_2 - m_2] *\
factorials[a6] *\
factorials[l_3 - m_3] *\
factorials[l_3 + m_3])
if include4Pi:
prefac1 /= (sympy.sqrt(sympy.pi) * sympy.Integer(2))

prefac2 = factorials[bigL] * factorials[a1] * factorials[a2] *
factorials[a3] /\
(factorials[2 * bigL + 1] *\
factorials[bigL - l_1] * factorials[bigL - l_2] *
factorials[bigL - l_3])

sumres = 0
for ii in range(imin, imax + 1):
den = factorials[ii] * factorials[a1 - ii] *\
factorials[ii - a4] * factorials[ii - a5] *\
factorials[a6 - ii] * factorials[a7 - ii]
if np.mod(ii, 2) == 0:
sumres += sympy.Integer(1) / den
else:
sumres -= sympy.Integer(1) / den
res = prefac1 * prefac2 * sumres
if np.mod((bigL + l_3 + m_1 - m_2), 2) != 0:
res = -res

if prec is not None:
res = res.evalf(prec)
return res

def store_Rasch_Yu(fileName, l_max):
filters = tables.Filters(complevel=1, complib='zlib')
#complib='zlib'|'blosc'
with tables.openFile(fileName, mode = "w") as fileh:
vlarray0 = fileh.createVLArray(fileh.root, 'vlarray',
tables.ObjectAtom(),
"pickled Gaunt coeffs", filters=filters,
expectedsizeinMB=(l_max*0.1)**4)

zeroList = []
indices = 0
for l_1 in xrange(l_max + 1):
for l_2 in xrange(l_1 + 1):
for l_3 in xrange(l_2 + 1):
if zero_gaunt_l(l_1, l_2, l_3):
for m_3 in xrange(l_3 + 1):
# vlarray0.append(zeroList)
indices += 1
continue
print l_1, l_2, l_3
for m_3 in xrange(l_3 + 1):
m3list = []
for m_2 in xrange(-l_2, min(l_1 - m_3, l_2) +
1):
m_1 = -m_2 - m_3
if zero_gaunt_m(l_1, l_2, l_3, m_1, m_2,
m_3):
curGaunt = sympy.Integer(0)
else:
curGaunt = calc_gaunt(l_1, l_2, l_3,
m_1, m_2, m_3,
include4Pi=False)
# if I comment calc_gaunt above and uncomment the one below with a
dummi
# set of indices, there is no memory problem
# curGaunt =
calc_gaunt(29,29,34,10,-5,-5,
# include4Pi=False)
if type(curGaunt) in \
[sympy.core.numbers.Integer,
sympy.core.numbers.Zero,
sympy.core.numbers.One,
sympy.core.numbers.NegativeOne]:
m2list = curGaunt
elif type(curGaunt) ==
sympy.core.numbers.Rational:
m2list = [curGaunt.p, curGaunt.q]
elif type(curGaunt) == sympy.core.mul.Mul:
m2list = [0, 1, 0]
for bas_arg in
curGaunt.iter_basic_args():
if type(bas_arg) ==
sympy.core.numbers.Rational:
m2list[0] = bas_arg.p
m2list[1] = bas_arg.q
elif type(bas_arg) ==
sympy.core.power.Pow:
if bas_arg.exp ==
sympy.Integer(1)/2:
m2list[2] = bas_arg.base
else:
raise ValueError('wrong type
of Gaunt atoms')
if (m2list[0] == 0) or (m2list[2] ==
0):
raise ValueError('wrong value of
Gaunt')
else:
print l_1, l_2, l_3, m_1, m_2, m_3
print curGaunt, type(curGaunt)
raise ValueError('wrong type of Gaunt
result')
m3list.append(m2list)
# vlarray0.append(m3list)
indices += 1
# vlarray0.flush()
# print 'collecting garbage...',
# gc.collect()
# print ' done'

max_index_expected = (l_max + 1) * (l_max + 2) * (l_max + 3) *
(l_max + 4) / 24
print indices, max_index_expected

if __name__ == '__main__':
#!!!!!!!!!!!!!!!! VERY important !!!!!!!!!!!!!!!!
#in sympy/core/numbers.py, line 1013:
## The following is an algorithm where we collect perfect roots
## from the factors of base
#if b > 4294967296:
# # Prevent from factorizing too big integers
# return None
# <------------------- comment it out!!!
#end of !!!!!!!!!!!!!!!! VERY important !!!!!!!!!!!!!!!!

tstart = time.time()
store_Rasch_Yu('test_Rasch_Yu.h5', 30)
tstop = time.time()
print 'The calculation took {0:.1f} s'.format(tstop - tstart)

Øyvind Jensen

unread,
Sep 3, 2010, 12:19:23 PM9/3/10
to sy...@googlegroups.com
fr., 03.09.2010 kl. 09.08 -0700, skrev klmn:
> Dear all,
>
> I am trying to implement various schemes for storing Gaunt
> coefficients (integrals of 3 spherical harmonics) calculated
> symbolically. Ondrej, I remember you offered me help for this, now I
> have to ask for it.
>
> It appears that at moderately big indices, already at l_max~30, the
> memory is all eaten up. I tried to force garbage collection, without
> success. Interestingly, if I repeatedly calculate just one Gaunt
> coefficient for a fixed set of indices, there is no memory problem
> (commented out in the script below)…

What do you mean by "force garbage collection"? Have you tried

>>> sympy.cache.clear_cache()

Øyvind

klmn

unread,
Sep 3, 2010, 3:22:34 PM9/3/10
to sympy
Wow, what a fast and exact answer! clear_cache does the job. Thank you
Øyvind!

> What do you mean by "force garbage collection"?  
gc.collect()

Regards,
Konstantin

gkat...@gmail.com

unread,
Mar 2, 2016, 11:49:14 AM3/2/16
to sympy
What is the exact function of the clear?
Could someone explain to me, Thankful.

from sympy import *
k=factorint(13**10**6)
cache.clear_cache()
print (k)
Ps; Google Translate

Jason Moore

unread,
Mar 5, 2016, 4:03:15 PM3/5/16
to sy...@googlegroups.com
SymPy uses a cache to store results of computations so that you don't have expend much computational effort when doing repetitions of computations. You can manually clear that cache if you want using the function you show.

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at https://groups.google.com/group/sympy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/446759f5-1b20-49bb-9a49-741aa892ebf5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

gkat...@gmail.com

unread,
Mar 5, 2016, 5:36:27 PM3/5/16
to sympy
Gratitude.
Reply all
Reply to author
Forward
0 new messages