The Voidspace Techie Blog

Gravatar I tried your test code on my dual core MacBook with Python 2.5. I saw 99% usage when just thread 1 was running, and ~130% usage when thread 2 started. (OS X top does the usual 100% = 1 CPU normalization)

In any event, 130% isn't great either. Python's poor threading support could be an opportunity for people who work on other concurrent execution paradigms though. (Reasoning about concurrent execution with shared state is hard, as many of these researchers point out. It's like writing an OS without memory protection.)

A higher-level view of concurrency is going to be needed to really take advantage of the 2, 4 or 8 (!!) core CPUs coming in the next 5 years. And Python's thread handicap makes it a ripe market to test your new idea on.


Gravatar I only have a limited understanding of the internals of CPython, but i believe that all python threads are run on one cpu anyway, as there is a global mutex to protect everything anyway, so you cant actually get multi-cpu perfomance using threads with python, you have to use seperate processes (thus losing shared memory, easy condition waiting) and ipc. I would assume this is something that is getting alot of attention though.

Testing on my dual processor single core machine, i get 100% cpu usage for 1 cpu with 1 thread, and about 52-54% cpu useage for each cpu with two threads, which suggests what i stated above, but as with all things like this there may be more to it.


Gravatar The GIL is basically a lock on the python internals - so each thread has to wait for the other to use internal stuff.

I am pretty sure it won't work on Windows but on Mac or Linux you should be able to use fork() and get much better use out of a dual core because you have two separate processes.

Again this is the shared nothing direction discussed in the comments of your entry on threads - by isolating a process from its parents and letting it do it's own thing it can go off and freely take advantage of other resources without needing to worry it is stepping on feet of other threads. I suspect that as dual core machines become more common we will see less threading and more processes.


Gravatar Typically when I want to use multiple cores/processors I tend to either break the code up and run each piece on a separate process or run multiple instances of the code on each processor while using messaging to communicate with each other. I tend to only use threads when most of them will be sitting idle the majority of the time. I find using messaging to be a much saner approach especially in complex application.

Python does not need to change to support the approach I use but I believe Python's poor support for multi-cores is likely to hurt the Python community even though in reality it does not need to be an issue. It's just to unleash the full power of the cores it's going to mean people will need to change the way they program to fit within Python or Python will need to make changes to support the expected behavior that most people expect and allow threads to run on different processors and in an efficient way.

John


Gravatar The short verison:

If you're in Python code, you're holding the GIL.

If you're in C code, you may not be holding the GIL.

So, if you want to crunch numbers on multiple cores, you need to do it in C and explicitly write it s.t. it gives up the GIL.


Gravatar For easy real multi-threading with python, you may want to look at ipython1, the next generation of ipython, adressing the issues discussed above (with a server-client interpreter aproach).


Gravatar Or for really simple parallel processing, look at the parallel/pprocess module:

http://www.python.org/pypi/parallel

I've run the "embarrassingly parallel" Pygmy example on dual multicore hardware (or perhaps quad CPU - I don't remember), and you get to use all the cores.

It won't work on Windows until someone makes a decent version of the fork system call available, but that's apparently just a matter of updating the win32 stuff in the standard library.


Gravatar Here my results (tested on ubuntu):

1) python 2.4.3
one thread:
cpu1: 3%
cpu2: 100%
both threads:
cpu1, cpu2: 50-60%

2) jython (2.1 and 2.2a)
one thread:
cpu1, cpu2: 0-100% (both are used alternately)
both threads:
cpu1, cpu2: 98-100% (truly parallel)


Gravatar The comparison with CPython and Jython may be true but it's likely that the code running under CPython will execute faster on one processor than the same code on Jython running on 2 processors.


Gravatar Of course, I was just comparing the behaviour in a with/without GIL environment. In *short running processes* it's out of question that jython is slower (specially by its startup time).


Gravatar Maybe another reason to start looking what's Beyond Python...


Gravatar Hey Hans, good to hear from you. What do you have in mind ?


Gravatar Hmm, maybe a language with multithreading built in, like Erlang or Io. I like the latter a lot, but it's not in very good shape at the moment. Also, I'm not claiming it will actually do better at this particular problem (as described in the blog post), BTW.


Gravatar Erlang certainly has a lot of mindshare for concurrency, and it sounds very interesting. I have no idea what it is like as a programming langauge though.

Fuzzy


Gravatar May it's time to give a try for Stackless Python? It has very effective "green threads" inside python without spawning system threads.


Gravatar I came across this post while googling for an answer of my astonishment over this.

This is my results on a 8 core MacPro with modified code ofc

1: 100%
2: 153%
3: 180%
4: 194%
5: 190%
6: 194%
7: 194%
8: 199%


code (indentation gets lost ofc >_< )

import time
from threading import Thread

def BurnCycles():
x = 0
while True:
x += 1

for i in range( 8 ):
print 'Starting Thread', i
t = Thread(target=BurnCycles)
t.start()
time.sleep(10)


Gravatar I also tried with python3.0. It was actualy worse; stopping at 154%


Name:

Email:

URL:

Comment:  ? 

 

Commenting by HaloScan