By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,941 Members | 1,753 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,941 IT Pros & Developers. It's quick & easy.

threads and sleep?

P: n/a
Hello all,

I am in the process of writing a multithreading program and what I was
wondering is a sleep command in an executing function will affect the
threads below it? Here is a basic example of what I mean.

def main():
temp_var = True
while temp_var == True:
if
t = threading.Thread( target = func1, args = "String") #note
this is probably non functional (example purposes for the question
only)
t.start()
temp_var = t.isAlive()
else:
print "This line should display a lot"
sleep(2)

def func1(s):
print s

so the question I was wondering is if the sleep will pause the t
thread as well as the main function or is the thread independat of the
main function sleep?

Thanks in advance.
Jul 21 '05 #1
Share this Question
Share on Google+
29 Replies


P: n/a
Jeffrey Maitland wrote:
I am in the process of writing a multithreading program and what I was
wondering is a sleep command in an executing function will affect the
threads below it?
Note that the "executing function" is itself running inside a thread,
specifically the "main thread". The other threads are not "below" it in
any particular sense, more like beside it. (Or, to put it another way,
there is no such concept of relative position with threads in Python.)

Here is a basic example of what I mean.
[snip code] so the question I was wondering is if the sleep will pause the t
thread as well as the main function or is the thread independat of the
main function sleep?


Your code is very close to working already... why don't you just run it
and observe how it works?

In any case, the answer is "no, time.sleep() affects only the current
thread".

-Peter
Jul 21 '05 #2

P: n/a
On Mon, 04 Jul 2005 18:36:07 -0400, Peter Hansen <pe***@engcorp.com>
declaimed the following in comp.lang.python:

In any case, the answer is "no, time.sleep() affects only the current
thread".
Heck, it is one of the means of getting number-crunchers to give
up the CPU to allow other threads/processes to run <G>

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Jul 21 '05 #3

P: n/a
Hello all,

First off Thanks for the responses on the sleep() part I suspected as
much but I wasn't 100% sure.

To continue this I just want to pre thank anyone that contributes to
this thread(lol).

Ok here goes. The problem I have is I had an application
(wrote/co-wrote) that has a long run time dependant on some variables
passed to it (mainly accuracy variables, the more accurate the longer
the run time - makes sense). However in the hopes to speed it up I
decided to write a threaded version of the program to try and speed
it up. How ever what I am noticing is that the threaded version is
taking as long possibly longer to run. The thing is the threaded
version is running on an 8 ia-64 proccessor system and it seems to
only be using 2 or 3 porcessors at about 30% (fluxiates). My guess is
that 6 threads are running they are using 30% sprox each of a 2 given
CPUS.

What I would like to do is have say 1 thread use as much of a given
CPU as possible and if a new thread is started (added) that if a CPU
is available use it instead of using the same cpu. That way it should
speed the application up. The standalone (non-threaded) app uses 90+
% of a single cpu when in this part of the algorithm, that is why I
split and threaded that part of the algorithm there to try and speed
it up because this part is repeated several times. I can post
generic code of what I am doing but can't post the actuall code
because of the confidentially of it. Thanks again in advance for any
and all comments (even any spitefull ones)

Jeff
Jul 21 '05 #4

P: n/a
Jeffrey Maitland wrote:
The problem I have is I had an application
(wrote/co-wrote) that has a long run time dependant on some variables
passed to it (mainly accuracy variables, the more accurate the longer
the run time - makes sense). However in the hopes to speed it up I
decided to write a threaded version of the program to try and speed
it up. How ever what I am noticing is that the threaded version is
taking as long possibly longer to run. The thing is the threaded
version is running on an 8 ia-64 proccessor system and it seems to
only be using 2 or 3 porcessors at about 30% (fluxiates). My guess is
that 6 threads are running they are using 30% sprox each of a 2 given
CPUS.


In many ways, Python is an incredibly bad choice for deeply
multithreaded applications. One big problem is the global interpreter
lock; no matter how many CPUs you have, only one will run python code
at a time. (Many people who don't run on multiple CPUs anyway try to
wave this off as a non-problem, or at least worth the tradeoff in terms
of a simpler C API, but with multicore processors coming from every
direction I think the "let's pretend we don't have a problem" approach
may not work much longer.)

If the GIL isn't an issue (and in your case it clearly is), you'll
quickly find that there's little support for debugging multithreaded
applications, and even less for profiling.

Sometimes running multiple processes is an acceptable workaround; if
not, good luck with the rewrite in Java or something else with real
thread support. (IIRC Jython doesn't have a GIL; that might be an
option too.)

Python is a great tool but if you really need good threading support
you will have to look elsewhere.

-Jonathan

Jul 21 '05 #5

P: n/a
On 2005-07-05, Jeffrey Maitland <je***********@gmail.com> wrote:
Ok here goes. The problem I have is I had an application
(wrote/co-wrote) that has a long run time dependant on some variables
passed to it (mainly accuracy variables, the more accurate the longer
the run time - makes sense). However in the hopes to speed it up I
decided to write a threaded version of the program to try and speed
it up. How ever what I am noticing is that the threaded version is
taking as long possibly longer to run. The thing is the threaded
version is running on an 8 ia-64 proccessor system and it seems to
only be using 2 or 3 porcessors at about 30% (fluxiates). My guess is
that 6 threads are running they are using 30% sprox each of a 2 given
CPUS.


Because of the global interpreter lock, a multi-threaded python
program does not take advantage of multiple processors. No
matter how many CPUs you have, only one thread is allowed to
run at any point in time.

Multi-threading in Python is useful for simplifying the
architecture of a program that has to do multiple independent
tasks, but it isn't useful for actually running multiple
threads in parallel.

--
Grant Edwards grante Yow! Inside, I'm already
at SOBBING!
visi.com
Jul 21 '05 #6

P: n/a
On Tue, 5 Jul 2005 10:57:18 -0400, Jeffrey Maitland
<je***********@gmail.com> declaimed the following in comp.lang.python:
it up. How ever what I am noticing is that the threaded version is
taking as long possibly longer to run. The thing is the threaded
Well, threading does add some overhead in terms of the task swap
time.
version is running on an 8 ia-64 proccessor system and it seems to
only be using 2 or 3 porcessors at about 30% (fluxiates). My guess is
that 6 threads are running they are using 30% sprox each of a 2 given
CPUS.

What I would like to do is have say 1 thread use as much of a given
CPU as possible and if a new thread is started (added) that if a CPU
is available use it instead of using the same cpu. That way it should
Don't think you can do that with Python... The Python runtime
interpreter itself is running on a single processor. The second thing is
the infamous "global interpreter lock" (pull up the Python documentation
and do a search for that phrase). Basically, even if the threads could
be assigned to processors, this lock means only one thread can be
performing Python operations at a time -- a C-language number crunching
module /could/ release the lock, then do its number crunching in
parallel, reacquiring the lock when it finishes so it can return its
result(s) as Python objects.

You might get the results you want by not using threads, instead
spawning off completely new Python invocations assigned to other
processors.

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Jul 21 '05 #7

P: n/a
Jeffrey Maitland <je***********@gmail.com> writes:
What I would like to do is have say 1 thread use as much of a given
CPU as possible and if a new thread is started (added) that if a CPU
is available use it instead of using the same cpu. That way it should
speed the application up. The standalone (non-threaded) app uses 90+
% of a single cpu when in this part of the algorithm, that is why I
split and threaded that part of the algorithm there to try and speed
it up because this part is repeated several times. I can post
generic code of what I am doing but can't post the actuall code
because of the confidentially of it. Thanks again in advance for any
and all comments (even any spitefull ones)


This kind of fine control over CPU allocation is very
plaform-specific. Some don't allow it at all. If your platform does,
the details on how you go about doing it will vary depending on the
platform.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Jul 21 '05 #8

P: n/a
Thanks.

I was hoping that python would allow for the cpu threading such in
Java etc.. but I guess not. (from the answers,and other findings) I
guess I will have to write this part of the code in something such as
java or c or something that allows for it then I can either wrap it in
python or avoid python for this part of the app.

Thanks for all the help.
Jul 21 '05 #9

P: n/a
On 2005-07-05, Dennis Lee Bieber <wl*****@ix.netcom.com> wrote:
Don't think you can do that with Python... The Python runtime
interpreter itself is running on a single processor.
I don't see how that can be. Under Linux at least, the Python
threading module uses "real" OS threads, so there are multiple
instances of the interpreter, right? Generally all but one of
them will be blocked on the GIL, but there are still multiple
interpreter threads (which can be on multiple different CPUs).

Or is the Python interpreter actually doing the context
switches itself?
The second thing is the infamous "global interpreter lock"
(pull up the Python documentation and do a search for that
phrase).
The GIL is the issue.
Basically, even if the threads could be assigned to
processors,
Can somebody explani why they can't?
this lock means only one thread can be performing Python
operations at a time -- a C-language number crunching module
/could/ release the lock, then do its number crunching in
parallel, reacquiring the lock when it finishes so it can
return its result(s) as Python objects.
True. Python can execute C code in parallel, but not Python
code.
Tou might get the results you want by not using threads,
instead spawning off completely new Python invocations
assigned to other processors.


That should work, but managing the inter-process communication
and syncronization is a pain.

--
Grant Edwards grante Yow! If Robert Di Niro
at assassinates Walter Slezak,
visi.com will Jodie Foster marry
Bonzo??
Jul 21 '05 #10

P: n/a
On 2005-07-05, Grant Edwards <gr****@visi.com> wrote:
Don't think you can do that with Python... The Python runtime
interpreter itself is running on a single processor.


I don't see how that can be. Under Linux at least, the Python
threading module uses "real" OS threads, so there are multiple
instances of the interpreter, right? Generally all but one of
them will be blocked on the GIL, but there are still multiple
interpreter threads (which can be on multiple different CPUs).

Or is the Python interpreter actually doing the context
switches itself?


Upon further thought, that just can't be the case. There has
to be multiple instances of the intepreter because the
interpreter can make C system calls that block (thus blocking
that instance of the interpreter). Other Python threads within
the program continue to run, so there must be multiple Python
intepreters.

--
Grant Edwards grante Yow! I'm wearing PAMPERS!!
at
visi.com
Jul 21 '05 #11

P: n/a
Jeffrey Maitland wrote:
I was hoping that python would allow for the cpu threading such in
Java etc.. but I guess not. (from the answers,and other findings) I
guess I will have to write this part of the code in something such as
java or c or something that allows for it then I can either wrap it in
python or avoid python for this part of the app.


Or investigate the use of Irmen's Pyro package and how it could let you
almost transparently move your code to a *multi-process* architecture
which would then let you take advantage of all the CPUs you have
available (even if they _aren't_ on the same machine!).

-Peter
Jul 21 '05 #12

P: n/a
On Tue, 05 Jul 2005 16:01:23 -0000, Grant Edwards <gr****@visi.com>
declaimed the following in comp.lang.python:

Or is the Python interpreter actually doing the context
switches itself?
It would seem to be close to doing that, if it has that internal
"quantum" of releasing the GIL every 100 bytecodes... At the least, the
GIL release/reacquire would be similar to having a C-language program
doing sleep() to let other tasks run. I'll admit that I don't know if
creating a Python thread also creates a new interpreter from scratch
(after all, Windows doesn't have a fork() operation). It may be that the
GIL toggle is part of a thread state save/restore operation, and could
thereby be looked on as a high-level context switch with the OS-level
context switch basically selecting from the threads blocked on the GIL.
{I'm going to louse up the message tracking here by pasting part of your
follow-up into one response}

2> Upon further thought, that just can't be the case. There has
2> to be multiple instances of the intepreter because the
2> interpreter can make C system calls that block (thus blocking
2> that instance of the interpreter). Other Python threads within
2> the program continue to run, so there must be multiple Python
2> intepreters.

From the documentation:

"""
The lock is also released and reacquired around potentially blocking I/O
operations like reading or writing a file, so that other threads can run
while the thread that requests the I/O is waiting for the I/O operation
to complete.
"""

It will take someone who's actually worked on the runtime
interpreter, or studied the code, to, uhm, "interpret" all the above
tidbits...

That should work, but managing the inter-process communication
and syncronization is a pain.
No argument there... If processor affinities and heavy cpu usage
are involved, with no pre-existing language bias, I'd suggest Ada (GNAT
or current derivative) with maybe the distributed systems annex (I'm not
sure if that is just inter-box distributed, or applicable to
multi-processor boxes).

Otherwise, I'd say convert the number cruncher to a compiled
module that can be started as a Python thread, drop into the compiled
code, give up the GIL, and crunch away -- only acquiring the GIL when it
has results to give back.

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Jul 21 '05 #13

P: n/a
Peter Hansen wrote:
Jeffrey Maitland wrote:
I was hoping that python would allow for the cpu threading such in
Java etc.. but I guess not. (from the answers,and other findings) I
guess I will have to write this part of the code in something such as
java or c or something that allows for it then I can either wrap it in
python or avoid python for this part of the app.


Or investigate the use of Irmen's Pyro package and how it could let you
almost transparently move your code to a *multi-process* architecture


Unless you're doing anything that would require distributed locking.
Many if not most such projects do, which is why almost everyone prefers
to use threads on an SMP machine instead of splitting it across
multiple smaller boxes.

-Jonathan

Jul 21 '05 #14

P: n/a
Jonathan Ellis wrote:
Peter Hansen wrote:
Or investigate the use of Irmen's Pyro package and how it could let you
almost transparently move your code to a *multi-process* architecture


Unless you're doing anything that would require distributed locking.
Many if not most such projects do, which is why almost everyone prefers
to use threads on an SMP machine instead of splitting it across
multiple smaller boxes.


I can't address the issue of whether or not "most" such projects require
distributed locking, because I'm not familiar with more than half of
such projects, as you appear to be. <wink>

On the other hand, I am (somewhat) familiar with Jeffrey's stated
problem area (two postings of his earlier in the thread) and it really
doesn't sound like he needs such a thing. Would you normally expect to
need distributed locking for a simple system where you had long-running
computations and wanted to improve performance by using multiple CPUs?

Of course, only he can tell for sure.

-Peter
Jul 21 '05 #15

P: n/a
Grant Edwards wrote:
On 2005-07-05, Grant Edwards <gr****@visi.com> wrote:
Or is the Python interpreter actually doing the context
switches itself?


Upon further thought, that just can't be the case. There has
to be multiple instances of the intepreter because the
interpreter can make C system calls that block (thus blocking
that instance of the interpreter). Other Python threads within
the program continue to run, so there must be multiple Python
intepreters.


Maybe you should consider and explain what you mean by "multiple
interpreters"? As I understand the concept, and based on my several
years' old reading of the virtual machine code, I wouldn't say there are
multiple interpreters.

There's a reason the GIL is the *global* interpreter lock...

-Peter
Jul 21 '05 #16

P: n/a
On 2005-07-06, Dennis Lee Bieber <wl*****@ix.netcom.com> wrote:
On Tue, 05 Jul 2005 16:01:23 -0000, Grant Edwards <gr****@visi.com>
declaimed the following in comp.lang.python:
Or is the Python interpreter actually doing the context
switches itself?
It would seem to be close to doing that, if it has that internal
"quantum" of releasing the GIL every 100 bytecodes...


Right, but I think that's just _allowing_ a context switch
rather than performing one. The other interpreters are blocked
waiting for the GIL and releasing it lets one of them run.
Though the effect is pretty much the same, it's quite different
than having a single interpreter that does the scheduling and
context switching itself within a single OS process/thread.
At the least, the GIL release/reacquire would be similar to
having a C-language program doing sleep() to let other tasks
run. I'll admit that I don't know if creating a Python thread
also creates a new interpreter from scratch (after all,
Windows doesn't have a fork() operation).
If I were doing it, I don't think I'd use fork() and create a
second address space. I'd use a "lightweight" thread. All of
the interpreter instances would share a single address space.
I know that Win32 has threads.
It may be that the GIL toggle is part of a thread state
save/restore operation, and could thereby be looked on as a
high-level context switch with the OS-level context switch
basically selecting from the threads blocked on the GIL.
Right -- I think that's what's hapenning. I really ought to go
look at the CPython source code instead of just sputing
conjecture.
{I'm going to louse up the message tracking here by pasting part of your
follow-up into one response}

2> Upon further thought, that just can't be the case. There has
2> to be multiple instances of the intepreter because the
2> interpreter can make C system calls that block (thus blocking
2> that instance of the interpreter). Other Python threads within
2> the program continue to run, so there must be multiple Python
2> intepreters.

From the documentation:

"""
The lock is also released and reacquired around potentially blocking I/O
operations like reading or writing a file, so that other threads can run
while the thread that requests the I/O is waiting for the I/O operation
to complete.
"""
I know. I've worked on modules that release the GIL and call
blocking operations. My point is that when an interpreter
calls a blocking operation, the interpreter itself blocks. It
stops running. It goes to sleep. But, other Python threads
keep running, so there must be other interpreters running those
threads.
Otherwise, I'd say convert the number cruncher to a compiled
module that can be started as a Python thread, drop into the
compiled code, give up the GIL, and crunch away -- only
acquiring the GIL when it has results to give back.


Unfortunately that means you've got to debug a number cruncher
that's written in C.

--
Grant Edwards grante Yow! I'm shaving!! I'M
at SHAVING!!
visi.com
Jul 21 '05 #17

P: n/a
On 2005-07-06, Peter Hansen <pe***@engcorp.com> wrote:
Or is the Python interpreter actually doing the context
switches itself?
Upon further thought, that just can't be the case. There has
to be multiple instances of the intepreter because the
interpreter can make C system calls that block (thus blocking
that instance of the interpreter). Other Python threads within
the program continue to run, so there must be multiple Python
intepreters.


Maybe you should consider and explain what you mean by
"multiple interpreters"?


That in a multi-theraded Python program, the code that
impliments the Python VM is executing "simultaneously" in
multiple contexts: one for each thread (and possibly one master
thread).

I was responding to somebody who said that there were two issue
with using multiple CPUs:

1) the interpreter (singular) only ran on one CPU.

2) the GIL.

My point was that 1) couldn't be true. There must be multiple
instances of the interpreter since in a multi-threaded Python
program, the interpeter blocks when making libc calls like
read() write() recv() send(), and yet other Python threads
continue to run. If there _were_ only a single interpeter, and
it ran only on a single CPU, then the GIL wouldn't be needed.
As I understand the concept, and based on my several years'
old reading of the virtual machine code, I wouldn't say there
are multiple interpreters.

There's a reason the GIL is the *global* interpreter lock...


Exactly.

--
Grant Edwards grante Yow! I've been WRITING
at to SOPHIA LOREN every 45
visi.com MINUTES since JANUARY 1ST!!
Jul 21 '05 #18

P: n/a
Thanks for the info.

I was doing some more diggging and I came across a module/class
called POSH which should allow me to do what I want. My question now
is, has anyone here used this and if so what it as easy to implement
as what I am reading it is? (I have to wait for the sys admin to
install the module on that server, but I have made a modified
implemted the syntax into a copy of the code to test it as soon as the
admin installs it.)

Once again thanks for the information that you all have shared.

Jeff
Jul 21 '05 #19

P: n/a
Peter Hansen wrote:
Jonathan Ellis wrote:
Peter Hansen wrote:
Or investigate the use of Irmen's Pyro package and how it could let you
almost transparently move your code to a *multi-process* architecture


Unless you're doing anything that would require distributed locking.
Many if not most such projects do, which is why almost everyone prefers
to use threads on an SMP machine instead of splitting it across
multiple smaller boxes.


I can't address the issue of whether or not "most" such projects require
distributed locking, because I'm not familiar with more than half of
such projects, as you appear to be. <wink>


Your sarcasm is cute, I suppose, but think about it for a minute. If
the opposite of what I assert is true, why would even the mainstream
press be running articles along the lines of "multicore CPUs mean
programming will get tougher because locking is hard to get right and
you can't just scale by relying on the cpu to run your one
thread/process really fast anymore."

http://www.gotw.ca/publications/concurrency-ddj.htm for one example.

-Jonathan

Jul 21 '05 #20

P: n/a
Jonathan Ellis wrote:
Peter Hansen wrote:
I can't address the issue of whether or not "most" such projects require
distributed locking, because I'm not familiar with more than half of
such projects, as you appear to be. <wink>


Your sarcasm is cute, I suppose, but think about it for a minute. If
the opposite of what I assert is true, why would even the mainstream
press be running articles along the lines of "multicore CPUs mean
programming will get tougher because locking is hard to get right and
you can't just scale by relying on the cpu to run your one
thread/process really fast anymore."

http://www.gotw.ca/publications/concurrency-ddj.htm for one example.


Thanks, but then let me remove the last (sarcastic) part, the "as you
appear to be", and just leave the rest as is. I am *not* familiar with
this issue, but nevertheless still feel that the OP's problem does not
involve any such locking, so although it's quite possible that you are
correct, I have nothing more to add on the matter. If you think he
needs locking, and that therefore multi-process stuff via Pyro might not
work, he's probably the guy to talk to... I happen to feel it would
probably work fine.

-Peter
Jul 21 '05 #21

P: n/a
Grant Edwards wrote:
On 2005-07-06, Peter Hansen <pe***@engcorp.com> wrote:
Maybe you should consider and explain what you mean by
"multiple interpreters"?


That in a multi-theraded Python program, the code that
impliments the Python VM is executing "simultaneously" in
multiple contexts: one for each thread (and possibly one master
thread).


Okay, this description seems correct. Multiple threads, multiple
stacks, therefore multiple contexts and yes, by this definition,
multiple interpreters.

No "master thread" however. Just all the threads that are visible in
"threading.enumerate()", which includes the main thread (that the code
runs in at startup) and any new ones spawned afterwards.

-Peter
Jul 21 '05 #22

P: n/a
On 2005-07-07, Peter Hansen <pe***@engcorp.com> wrote:
Maybe you should consider and explain what you mean by
"multiple interpreters"?


That in a multi-theraded Python program, the code that
impliments the Python VM is executing "simultaneously" in
multiple contexts: one for each thread (and possibly one
master thread).


Okay, this description seems correct. Multiple threads,
multiple stacks, therefore multiple contexts and yes, by this
definition, multiple interpreters.

No "master thread" however. Just all the threads that are
visible in "threading.enumerate()", which includes the main
thread (that the code runs in at startup) and any new ones
spawned afterwards.


Oh. I assumed that CPython used Posix threads on Posix
platforms. At least in my experience under Linux, libpthread
always creates an extra "manager" thread. Though in our case
that thread probably wouldn't be running a Python interpreter.

--
Grant Edwards grante Yow! Uh-oh!! I'm having
at TOO MUCH FUN!!
visi.com
Jul 21 '05 #23

P: n/a
Am Donnerstag, den 07.07.2005, 22:56 +0000 schrieb Grant Edwards:
Oh. I assumed that CPython used Posix threads on Posix It does. platforms. At least in my experience under Linux, libpthread
always creates an extra "manager" thread. Though in our case It probably does. But it will probably not show as a Python thread.
Without some special interfacing with the Python/C API any thread
created in C will not show up in Python. that thread probably wouldn't be running a Python interpreter.


Andreas

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC1M3pHJdudm4KnO0RAjdOAJ0c/jw0Qb6Nk6HtQqvikPWoo9dTWgCgtXxj
Px9oRVOdZ4o9r1dfihvJC3Y=
=USOk
-----END PGP SIGNATURE-----

Jul 21 '05 #24

P: n/a
Am Dienstag, den 05.07.2005, 08:37 -0700 schrieb Jonathan Ellis:
In many ways, Python is an incredibly bad choice for deeply
multithreaded applications. One big problem is the global interpreter
lock; no matter how many CPUs you have, only one will run python code
at a time. (Many people who don't run on multiple CPUs anyway try to
wave this off as a non-problem, or at least worth the tradeoff in terms
of a simpler C API, but with multicore processors coming from every
direction I think the "let's pretend we don't have a problem" approach
may not work much longer.) Well, it's not a tradeoff in a simpler C API. It's a more complicated
thing. Much more complicated. ;) Basically nobody has been able to
propose a sensible solution for removing the GIL.

Any solution would have to have the following properties:

a) must be safe.
b) should be probably not slow as a snail ;)

The problem with a) is that loosing this property is not a proposition.
As it is probably a core benefit of Python. So the ceval function would
have to lock any object used it encounters when executing. Trouble: How
to deal with deadlocks. And it would entail locking and unlocking heaps
of objects on any line of Python code.

Basically the current state of art in "threading" programming doesn't
include a safe model. General threading programming is unsafe at the
moment, and there's nothing to do about that. It requires the developer
to carefully add any needed locking by hand. Any error in doing that
will give very hard to debug errors that might show up only in very
specific hardware configurations. And there is no way to detect these
errors automatically, which would be needed to raise a nice exception,
which is the standard at the moment in Python.

If the GIL isn't an issue (and in your case it clearly is), you'll
quickly find that there's little support for debugging multithreaded
applications, and even less for profiling.
As I've said above, there is a case that the current "safe computing"
model of Python isn't compatible with the current state of art in
threading.
Sometimes running multiple processes is an acceptable workaround; if
not, good luck with the rewrite in Java or something else with real
thread support. (IIRC Jython doesn't have a GIL; that might be an
option too.)
Jython might not have a GIL, but it probably will be have really bad
performance because it has to lock all kind of objects during
executation.

Python is a great tool but if you really need good threading support
you will have to look elsewhere.


Yes and no. For a completely general threading support, Python isn't
probably what one wants. OTOH general threading developement is a bit
more painful than many application developers want to endure. There are
ways to do a more structured threading in Python quite ok:

a) rewrite your number crunching thread stuff in C and release the GIL.
b) if you've got a task that can live with less communication -> one
might fork of some computation and communicate the results via pipe.
c) Live with the GIL.

While multi-core CPUs are coming, it will a time before the mainstream
hardware will get to more than 2 logical CPUs. You get quite a bit of
speedup already by delegating all the OS and other background tasks to
one CPU core.

And one thing one shouldn't forget is that finely multithreaded apps
aren't faster magically. If you spend need to add 50% more work for
locking, you will not get many benefits from threading on a 2 core box:

Assuming a two-core box does have about the processing power of 1.8
cores (because of memory contentation, and other problems. Depending
upon use and the exact hardware it might be even worse than that).

Now your single-threaded app runs 10seconds.
With locking this would be about 15seconds.
15 seconds divided by 1.8 gives 8.33seconds.

And that assumes that your application is perfectly threadable and will
have no contentation for data between it's threads. And it assumes a
favorable 1.8 speedup factor for 2 cores. And the hardware level
overhead for more cores goes up, especially if you run multiple threads
of one program -> because the fine interaction between this threads
raises the contentation for data between the cores/processors.

So, yes Python isn't multithreading well. At least not at the moment.
But this is basically there isn't currently a theoretical way to provide
the environment that Python does safely in a multithreaded app without
an incredible performance hit.

Andreas

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC1MzxHJdudm4KnO0RApfHAKDfv0dS85IsWtryE1eD76 9kWJ/uOACgmfC9
s7GA2Mfe3Hax6leuMXvvpaA=
=UA5+
-----END PGP SIGNATURE-----

Jul 21 '05 #25

P: n/a
Am Mittwoch, den 06.07.2005, 04:00 +0000 schrieb Dennis Lee Bieber:
{I'm going to louse up the message tracking here by pasting part of
your
follow-up into one response}

2> Upon further thought, that just can't be the case. There has
2> to be multiple instances of the intepreter because the
2> interpreter can make C system calls that block (thus blocking
2> that instance of the interpreter). Other Python threads within
2> the program continue to run, so there must be multiple Python
2> intepreters.

From the documentation:

"""
The lock is also released and reacquired around potentially blocking
I/O
operations like reading or writing a file, so that other threads can
run
while the thread that requests the I/O is waiting for the I/O
operation
to complete.
"""

It will take someone who's actually worked on the runtime
interpreter, or studied the code, to, uhm, "interpret" all the above
tidbits...


Not really, it's quite trivial. Anything that touches the Python/C API
needs the GIL.

[Python] <--Python/C API --> [Python module in C] <--some API--> [legacy Ccode]

Now a well behaved Python C module does release the GIL before doing
anything that might block/take a long time.

The drawback in a Python with threading support that runs just one
thread is the additional locking overhead. OTOH it's only done for
operatations that will probably take a long time anyway. (And long is a
relative term here *g*).

Andreas

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC1M8QHJdudm4KnO0RAttXAJ9lwBoK1Qt0UNlnR6BKRG PQzUGLLwCgobXq
1roene7WUotvUa1YQPQLGQs=
=0dz8
-----END PGP SIGNATURE-----

Jul 21 '05 #26

P: n/a
Am Mittwoch, den 06.07.2005, 14:38 +0000 schrieb Grant Edwards:

Unfortunately that means you've got to debug a number cruncher
that's written in C.


If one is careful, one can use Pyrex :)

Andreas

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC1M9kHJdudm4KnO0RAnneAKCSNGqYG+PjnYjihhP3bq 3/3ymg9QCfdMVr
kis8pFHVZLExZJVKXpKTNS0=
=cF1L
-----END PGP SIGNATURE-----

Jul 21 '05 #27

P: n/a
Am Mittwoch, den 06.07.2005, 12:27 -0700 schrieb Jonathan Ellis:
Your sarcasm is cute, I suppose, but think about it for a minute. If
the opposite of what I assert is true, why would even the mainstream
press be running articles along the lines of "multicore CPUs mean
programming will get tougher because locking is hard to get right and


Easy ;)

They run these articles, because

-) they have copied it from the press releases.

-) it's partly true.

-) it's the current hype in processors.
That doesn't change the contrary facts:

-) the general threading programming model is very hard to get right.
It's basically at the moment where we were with memory management at C
level. Painful, and errorprone. Nothing to be happy about.

-) There is a spectrum of problems from "requires to be run in sequence"
to can be run on as many "work slaves via the internet". Fact is that
Python is bad at a certain slice (can benefit from tightly
interoperating threads). And that will not change that quickly, because
there are certain problems. But Python works quite well for the
neighboring segments, and it got a number of solutions for a number of
problems in this segment. (Be it Twisted, forking, threads + GIL, etc.)

Andreas

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQBC1Oc9HJdudm4KnO0RAimgAKC4Ajg8z0648bSrTZCHoj Kv7tRCKQCdHGj8
a0JEbF57Ftwj4oOPcPHti2A=
=en2+
-----END PGP SIGNATURE-----

Jul 21 '05 #28

P: n/a
Andreas Kostyrka <an*****@kostyrka.org> writes:
That doesn't change the contrary facts:

-) the general threading programming model is very hard to get right.
It's basically at the moment where we were with memory management at C
level. Painful, and errorprone. Nothing to be happy about.


I'd say the common threading programming model is very hard to get
right. There are other models that are easy to get right. They've
been around for 20+ years. The problem is, they didn't make it into
any popular languages, so you're stuck with the model that you talk
about. Or maybe you're aware of those, and are saying all of those
models aren't "right" in some way?

People say good things about using the Queue module for Python. I
haven't investigated it thoroughly, so I have no idea how general it
is.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Jul 21 '05 #29

P: n/a
Andreas Kostyrka <an*****@kostyrka.org> writes:
Basically the current state of art in "threading" programming doesn't
include a safe model. General threading programming is unsafe at the
moment, and there's nothing to do about that. It requires the developer
to carefully add any needed locking by hand.


So how does Java do it? Declaring some objects and functions to be
synchronized seems to be enough, I thought.
Jul 21 '05 #30

This discussion thread is closed

Replies have been disabled for this discussion.