[Numpy-discussion] "import numpy" is slow

Andrew Dalke dalke at dalkescientific.com
Wed Jul 30 20:07:37 EDT 2008


On Jul 30, 2008, at 10:59 PM, Stéfan van der Walt wrote:
> I.e. most people don't start up NumPy all the time -- they import
> NumPy, and then do some calculations, which typically take longer than
> the import time.

Is that interactively, or is that through programs?

> For a benefit of 0.03s, I don't think it's worth it.

The final number with all the hundredths of a second added up to 0.08  
seconds, which was about 30% of the 'import numpy' cost.

> Numpy has a very flat namespace, for better or worse, which implies
> many imports.


I don't get the feeling that numpy is flat.  Python's stdlib is flat.  
Numpy has many 2- and 3-level modules.

>> Is the numpy recommendation that people should do:
>>
>>   import numpy
>>   numpy.fft.ifft(data)
>
> That's the way many people use it.

The normal Python way is:

  from numpy import fft
   fft.ifft(data)

because in most packages, parent modules don't import all of their  
children.  I acknowledge that existing numpy code will break with my  
desired change, as this example from the tutorial


   import numpy
   import pylab
   # Build a vector of 10000 normal deviates with variance 0.5^2 and  
mean 2
   mu, sigma = 2, 0.5
   v = numpy.random.normal(mu,sigma,10000)

and I am not saying to change this code.  Instead, I am asking for  
limits on the eagerness, with a long-term goal of minimizing its use.


>> Why is [ctypeslib] so important that it should be in the top-
>> level namespace?
>
> It's a single Python file -- does it make much of a difference?

The file imports other files.  Here's the import chain:

  ctypeslib: 0.047 (numpy)
   ctypes: -1.000 (ctypeslib)
    _ctypes: 0.003 (ctypes)
    gestalt: -1.000 (ctypes)
    ma: 0.005 (numpy)
     extras: 0.001 (ma)
      numpy.lib.index_tricks: 0.000 (extras)
      numpy.lib.polynomial: 0.000 (extras)

(The "-1.000" indicates a bug in my instrumentation script, which I  
worked around with a -1.0 value.)

Every numpy program, because it eagerly imports 'ctypeslib' to make  
it be accessible as a top-level variable, ends up importing ctypes.

 >>> if 1:
...   t1 = time.time()
...   import ctypes
...   t2 = time.time()
...
 >>> t2-t1
0.032159090042114258

That's 10% of the import time.


>> In my opinion, this assistance is counter to standard practice in
>> effectively every other Python package.  I don't see the benefit.
>
> How do you propose we change this?

If I had my way, remove things like (in numpy/__init__.py)

     import linalg
     import fft
     import random
     import ctypeslib
     import ma

but leave the list of submodules in "__all__" so that "from numpy  
import *" works.  Perhaps add a top-level function to 'import_all()'  
which mimics the current behavior, and have iPython know about it so  
interactive users get it automatically.  Or something like that.


Yes, I know the numpy team won't change this behavior.  I want to  
know why you all will consider changing.


Something more concrete: change the top-level definitions in 'numpy'  
from

     from testing import Tester
     test = Tester().test
     bench = Tester().bench

with

def test(label='fast', verbose=1, extra_argv=None, doctests=False,
              coverage=False, **kwargs):
   from testing import Tester
   Tester.test(label, verbose, extra_argv, doctests, coverage, **kwargs

and do something similar for 'bench'.  Note that numpy currently  
implements

   numpy.test  <-- this is a Tester().test
   numpy.testing.test <-- another Tester().test bound method

so there's some needless and distracting, but extremely minor,  
duplication.



>> Getting rid of these functions, and thus getting rid of the import
>> speeds numpy startup time by 3.5%.
>
> While I appreciate you taking the time to find these niggles, but we
> are short on developer time as it is.  Asking them to spend their
> precious time on making a 3.5% improvement in startup time does not
> make much sense.  If you provide a patch, on the other hand, it would
> only take a matter of seconds to decide whether to apply or not.
> You've already done most of the sleuth work.

I wrote that I don't know the reasons for why the design was as it  
is.  Are those functions ("english_upper", "english_lower",  
"english_capitalize") expected as part of the public interface for  
the module?  The lack of a "_" prefix and their verbose docstrings  
implies that they are for general use.  In that case, they can't  
easily be gotten rid of.  Yet it doesn't make sense for them to be  
part of 'numerictypes'.

Why would I submit a patch if there's no way those definitions will  
disappear, for reasons I am not aware of?

I am not asking you all to make these changes.  I'm asking about how  
much change is acceptable, what are the restrictions, and why are  
they there?


I also haven't yet figured out how to get the regression tests to  
run, and I'm not going to contribute patches without at least passing  
that bare minimum.  BTW, how do I do that?  In the top-level there's  
a 'test.sh' command but when I run it I get:

% mkdir tmp
% bash test.sh
Running from numpy source directory.
Traceback (most recent call last):
   File "setupscons.py", line 56, in <module>
     raise DistutilsError('\n'.join(msg))
distutils.errors.DistutilsError: You cannot build numpy with scons  
without the numscons package
(Failure was: No module named numscons)
test.sh: line 11: cd: /Users/dalke/cvses/numpy/tmp: No such file or  
directory

and when I run 'nosetests' in the top-level directory I get:

ImportError: Error importing numpy: you should not try to import  
numpy from
         its source directory; please exit the numpy source tree, and  
relaunch
         your python intepreter from there.

I couldn't find (in a cursory search) instructions for running self- 
tests or regression tests.


>> I could probably get another 0.05 seconds if I dug around more, but I
>> can't without knowing what use case numpy is trying to achieve.  Why
>> are all those ancillary modules (testing, ctypeslib) eagerly loaded
>> when there seems no need for that feature?
>
> Need is relative.  You need fast startup time, but most of our users
> need quick access to whichever functions they want (and often use from
> an interactive terminal).  I agree that "testing" and "ctypeslib" do
> not belong in that category, but they don't seem to do much harm
> either.

If there is no need for those features then I'll submit a patch to  
remove them.

There is some need, and there are many ways to handle that need.  The  
current solution in numpy is to import everything.  Again I ask, does  
*everything* (like 'testing' and 'ctypeslib') need to be imported  
eagerly?  In your use case of user-driven exploratory development the  
answer is no - the users described above rarely desire access to  
those package because those packages are best used in automated  
environments.  Eg, why write tests which are only used once?


				Andrew
				dalke at dalkescientific.com





More information about the NumPy-Discussion mailing list