[Image-SIG] Multi-threading and PIL
Mon, 2 Dec 2002 11:18:47 -0500
I've been working on a multi-threaded image processing application, and I've
seen that only one CPU of a multi-processor system is being used by Python
at a time, even if two threads are busy doing PIL processing.
I came across the post below talking about Python multi-threading using
"GIL" to control if a thread blocks others from executing or not... is it
possible to upgrade the PIL c DLL's to release the GIL while processing?
I'm not far into this yet, but it would be a huge advantage... anyone looked
at this yet?
"Michael Chermside" <email@example.com> wrote in message
> David Brown wrote:
> > I've just been reading a little about the GIL and threading in python,
> > have a couple of questions that I hope someone can answer.
> I'm not an expert, but I'll try.
> > Am I right in thinking that threading in Python does not use the
> > OS's threads, but effectively implements its own scheduler? Or does
> > the OS's threads, but uses the GIL to ensure that only one is runable
> > time?
> It uses the OS's threads, and then uses the GIL to ensure that only one
> is executing Python bytecodes at a time. However, other threads may be
> runable... they could be blocked waiting on I/O, or executing some C
> code from a module that releases the GIL before performing a
> long-running computation.
If C code (or other extensions) that take significant time, or block for
other reasons, release the GIL then there I suppose there is not going to be
much of a problem. The point is to maximize the throughput, and avoid
threads blocking each other unnecessarily.
> > On a dual-processor system, does this mean that only one thread of a
> > program can run at a time, even when both CPUs are free, so that two
> > seperate python interpreter processes are needed to take advantage of
> > two CPUs?
It sounds like that is only true for code that does a lot of work in pure
python (rather than with time-consuming, GIL-released C code).
> > What about when a Python thread is blocked for some other reason, such
> > while waiting for a file read - will that block other threads, or will
> > waiting thread definitely release the GIL and allow other threads to
> Depends on what it's blocked for. If it's blocked for I/O, then the GIL
> is released and the other threads will run. I'm not sure what else it
> would block for that might be a problem. But you could certainly CREATE
> a problem if you tried... simplest way would be to write C code which
> ran for a long time WITHOUT releasing the GIL.
> It would be much more difficult to block things through badly written
> Python code, since after each bytecode the interpretor can switch to a
> different thread.
> > If the GIL does block all threads in this manner, are there any plans to
> > introduce more fine-grained locking to improve scalability, analagous to
> > locking in the Linux kernel?
> No. The general consensus is that eliminating the GIL would be quite
> difficult and that there's not really all that much to gain. (Most
> casual users don't have multi-processor systems; serious users of this
> sort probably use Numeric and/or put the tight loops into C anyhow.)
> However, if you know someone who's good with this stuff and wants to
> volunteer, I'm sure they wouldn't turn down working code (unless it
> introduced other problems).
> -- Michael Chermside
Thanks for the information - it was definitely helpful. It looks like the
system used by Python will work fine in all but a few situations (SMP system
in which a lot of work is being done in Python itself, rather than in
extension modules - or in badly written extensions which don't release the
GIL before doing heavy work). Such situations can be dealt with by running
two python processes - if a program really needs to do hard SMP work in
python, then that is a small price to pay since I image the GIL simplifies a
lot of things. I had been worried that the Python threading scheme would
have caused more inefficiences (such as all threads stopping while a single
thread was blocked for I/O).