Skip to content

Commit

Permalink
Reduce numpy's import times by delaying a few time consuming imports …
Browse files Browse the repository at this point in the history
…to the point of actual use and global instantiations of finfo. Thanks to David Cournapeau for tracking down and fixing the import part of the problem.
  • Loading branch information
rkern committed Jul 3, 2008
1 parent 590babe commit 102cdc2
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 26 deletions.
7 changes: 6 additions & 1 deletion numpy/lib/_datasource.py
Expand Up @@ -37,7 +37,6 @@
import os
import tempfile
from shutil import rmtree
from urllib2 import urlopen, URLError
from urlparse import urlparse

# TODO: .zip support, .tar support?
Expand Down Expand Up @@ -196,6 +195,9 @@ def _cache(self, path):
Creates a copy of the file in the datasource cache.
"""
# We import these here because importing urllib2 is slow and
# a significant fraction of numpy's total import time.
from urllib2 import urlopen, URLError

upath = self.abspath(path)

Expand Down Expand Up @@ -337,6 +339,9 @@ def exists(self, path):
is accessible if it exists in either location.
"""
# We import this here because importing urllib2 is slow and
# a significant fraction of numpy's total import time.
from urllib2 import URLError

# Test local path
if os.path.exists(path):
Expand Down
14 changes: 8 additions & 6 deletions numpy/lib/getlimits.py
Expand Up @@ -21,14 +21,16 @@ def _frz(a):
}

class finfo(object):
"""Machine limits for floating point types.
""" Machine limits for floating point types.
:Parameters:
dtype : floating point type or instance
:SeeAlso:
- numpy.lib.machar.MachAr
Parameters
----------
dtype : floating point type, dtype, or instance
The kind of floating point data type to get information about.
See Also
--------
numpy.lib.machar.MachAr
"""

_finfo_cache = {}
Expand Down
8 changes: 1 addition & 7 deletions numpy/lib/polynomial.py
Expand Up @@ -17,8 +17,6 @@
from numpy.lib.function_base import trim_zeros, sort_complex
eigvals = None
lstsq = None
_single_eps = finfo(NX.single).eps
_double_eps = finfo(NX.double).eps

class RankWarning(UserWarning):
"""Issued by polyfit when Vandermonde matrix is rank deficient.
Expand Down Expand Up @@ -301,11 +299,7 @@ def polyfit(x, y, deg, rcond=None, full=False):

# set rcond
if rcond is None :
xtype = x.dtype
if xtype == NX.single or xtype == NX.csingle :
rcond = len(x)*_single_eps
else :
rcond = len(x)*_double_eps
rcond = len(x)*finfo(x.dtype).eps

# scale x to improve condition number
scale = abs(x).max()
Expand Down
3 changes: 2 additions & 1 deletion numpy/lib/tests/test__datasource.py
Expand Up @@ -5,6 +5,7 @@
from tempfile import mkdtemp, mkstemp, NamedTemporaryFile
from shutil import rmtree
from urlparse import urlparse
from urllib2 import URLError

from numpy.testing import *

Expand All @@ -16,7 +17,7 @@ def urlopen_stub(url, data=None):
tmpfile = NamedTemporaryFile(prefix='urltmp_')
return tmpfile
else:
raise datasource.URLError('Name or service not known')
raise URLError('Name or service not known')

# Rebind urlopen during testing. For a 'real' test, uncomment the rebinding
# below.
Expand Down
13 changes: 9 additions & 4 deletions numpy/lib/utils.py
@@ -1,11 +1,9 @@
import compiler
import os
import sys
import inspect
import pkgutil
import types
import re
import pydoc

from numpy.core.numerictypes import obj2sctype, generic
from numpy.core.multiarray import dtype as _dtype
from numpy.core import product, ndarray
Expand Down Expand Up @@ -327,7 +325,8 @@ def info(object=None,maxwidth=76,output=sys.stdout,toplevel='numpy'):
p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1]
"""
global _namedict, _dictlist
import pydoc
# Local import to speed up numpy's import time.
import pydoc, inspect

if hasattr(object,'_ppimport_importer') or \
hasattr(object, '_ppimport_module'):
Expand Down Expand Up @@ -467,6 +466,8 @@ def info(object=None,maxwidth=76,output=sys.stdout,toplevel='numpy'):
def source(object, output=sys.stdout):
"""Write source for this object to output.
"""
# Local import to speed up numpy's import time.
import inspect
try:
print >> output, "In file: %s\n" % inspect.getsourcefile(object)
print >> output, inspect.getsource(object)
Expand Down Expand Up @@ -599,6 +600,8 @@ def _lookfor_generate_cache(module, import_modules, regenerate):
"""
global _lookfor_caches
# Local import to speed up numpy's import time.
import inspect

if module is None:
module = "numpy"
Expand Down Expand Up @@ -751,6 +754,8 @@ def safe_eval(source):
...
SyntaxError: Unknown name: dict
"""
# Local import to speed up numpy's import time.
import compiler
walker = SafeEval()
try:
ast = compiler.parse(source, "eval")
Expand Down
8 changes: 6 additions & 2 deletions numpy/ma/core.py
Expand Up @@ -77,7 +77,6 @@
MaskType = np.bool_
nomask = MaskType(0)

divide_tolerance = np.finfo(float).tiny
np.seterr(all='ignore')

def doc_note(note):
Expand Down Expand Up @@ -398,9 +397,14 @@ def __call__ (self, x):
#............................
class _DomainSafeDivide:
"""Define a domain for safe division."""
def __init__ (self, tolerance=divide_tolerance):
def __init__ (self, tolerance=None):
self.tolerance = tolerance
def __call__ (self, a, b):
# Delay the selection of the tolerance to here in order to reduce numpy
# import times. The calculation of these parameters is a substantial
# component of numpy's import time.
if self.tolerance is None:
self.tolerance = np.finfo(float).tiny
return umath.absolute(a) * self.tolerance >= umath.absolute(b)
#............................
class _DomainGreater:
Expand Down
7 changes: 2 additions & 5 deletions numpy/ma/extras.py
Expand Up @@ -39,7 +39,7 @@
from numpy import ndarray, array as nxarray
import numpy.core.umath as umath
from numpy.lib.index_tricks import AxisConcatenator
from numpy.lib.polynomial import _lstsq, _single_eps, _double_eps
from numpy.lib.polynomial import _lstsq

#...............................................................................
def issequence(seq):
Expand Down Expand Up @@ -866,10 +866,7 @@ def polyfit(x, y, deg, rcond=None, full=False):
x[m] = y[m] = masked
# Set rcond
if rcond is None :
if x.dtype in (np.single, np.csingle):
rcond = len(x)*_single_eps
else :
rcond = len(x)*_double_eps
rcond = len(x)*np.finfo(x.dtype).eps
# Scale x to improve condition number
scale = abs(x).max()
if scale != 0 :
Expand Down

0 comments on commit 102cdc2

Please sign in to comment.