Performance hit for ALLOW_THREADS macros?

eric jones ej at ee.duke.edu
Fri Mar 30 10:23:35 CEST 2001


Hello,

Adding Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS appears to have
significant negative impact on my extension module's speed -- even when not
using threads. (Linux RH6.1, Python2.1a2)

I have a numeric routine that fills a large matrix.  The routine is written
in FORTRAN and lives in an extension module (wrapped by f2py).  The routine
has be written such that it can be called twice in parallel with one call
filling the upper half of the matrix and one filling the
lower half of the matrix (nice for multiprocessors).  Placing
Py_BEGIN_ALLOW_THREADS
and Py_END_ALLOW_THREADS around the call to the Fortran routine in the
extension module allows it to be called independently from two Python
threads.  Doing this provided very marginal speed-up (10-20% maybe).
Because of the run time of the routine (10s of seconds to days), I expected
a factor much closer to 100%. I played with sys.setcheckinterval() a little
to see if it helped things and it didn't.  This is what I expected reasoning
that all CPU cycles should be burning in the Fortran routines.

Looking for the issue, I ran the routine in single threaded mode, once
compiled with (1) Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS, and (2) once
without.  On a typical small problem, single threaded times showed the
following:

    (1) using ALLOW_THREADS macros   20.54 seconds
    (2) no macros                                         13.78 seconds

Why would simply adding these macros affect the run time so much?  I didn't
expect them to have any affect (especially when threads aren't even used).
Here's where I put the macros in the code.

    (1)
    static PyObject *foo(PyObject *capi_self, PyObject *capi_args, PyObject
*capi_keywds,     void (*f2py_func)()) {
    {
          ...
          Py_BEGIN_ALLOW_THREADS
          (*f2py_func)(&alpha,&i12,&cfreq,epstj,muej,...);
          Py_END_ALLOW_THREADS
          ...
    }

    (2)
    static PyObject *foo(PyObject *capi_self, PyObject *capi_args, PyObject
*capi_keywds,     void (*f2py_func)()) {
    {
          ...
          (*f2py_func)(&alpha,&i12,&cfreq,epstj,muej,...);
          ...
    }

Any hints as to what is happening here?

thanks,
eric






More information about the Python-list mailing list