The GIL Detector

Ever wonder if your flavor of python has a Global Interpreter Lock? The recipe gil_detector.py checks that.

In this day and age CPython is still core-locked; though we are seeing improvements thanks to Antoine Pitrou and other great people of the Python community. Wanting to measure just how bad the problem is – my way of looking at it was through a number I call the “python effective core count”.

Python Effective Core Count

How many cores does python see? If you bought a quad core, how many cores can each python process utilize? Measuring how long it takes to complete a given amount of work, W, then measuring how long it takes for python to run 2W using 2 threads, 3W on 3 threads, etc. The script gil_detector.py calculates:

effective_cpus = amount_of_work / (time_to_finish / baseline)

Where the baseline is the time_to_finish for 1 work unit. E.g. if it took the same amount of time to finish 4W (amount_of_work = 4) on 4 threads as it took 1W on 1 thread – python is utilizing 4 cores.

Results

I recommend reading the whole output to see the exact numbers.

Implementation Effective Core Count
Jython 2.5.2 3.8/4 cores
IronPython 2.7 3.2/4 cores
PyPy-1.5 1.0/4 cores
Stackless Python 3.2 1.0/4 cores
CPython 3.2 1.0/4 cores
CPython 2.7 0.2/4 cores

Basically, Jython has the best multithreading with IronPython not too far behind. I know multiprocessing is really easy in python, but it’s still harder. We have to solve this before 8 core CPU’s become the standard at grandma’s house. Those other languages (C/C++) utilize 3.9-4.0 cores of a quad core machine easily, why can’t we? An honorable mention goes to PyPy which by far was the fastest to execute the benchmark (10x faster). PyPy is definitely the future of Python, hopefully they can save us all. A note about CPython 2.7 – yes that number is under 1 because adding threads on python-cpu-intensive tasks hurt performance badly on older versions of the GIL, Antoine fixed that on CPython 3.2.

In my opinion the community should call this a bug and have a unittest in there yelling at us until we fix it, though it’s easy for me to complain when I’m not the core-dev. Maybe I can join PyPy and see what I can do when I find some free time. Hopefully so.

Edit – updated gil_detector.py as corrected at reddit.

About these ads

6 thoughts on “The GIL Detector

  1. This is a feature of Pythons deliberate choice to use green threads, and the artefacts of that decision run deep into the codebase. It doesn’t seem so clever now, but it must be remembered this path was taken long before the end of the Great Hertz Wars gave way to the Core Count Conflict of today.

    While I’m sure no-one will dispute that this is a big concern, it’s not as simple as you make it sound. C and C++ do *not* support threads at all, they need external libraries to do that, libraries that are not present across all platforms. The crusade against the GIL needs good C programmers experienced in the details of cross platform threading, complaining is something that is not needed, speaking as someone who has been guilty of that myself.

    • Python *does not* use green threads. It uses real system threads but has a Global Interpreter Lock (so only one of the system threads is executing *Python code* at any one time – although they can concurrently execute C code within the Python interpreter process).

  2. I use Python a lot, so please don’t take this as a criticism of Python. I like Python, although it does have its faults.

    I don’t see much point in focusing on making Python utilize all the cores of a CPU as fully as possible. Though with PyPy this might change.

    The reason for this is that Python is so inefficient to begin with that generally any efforts on performance tuning of a Python application would be best spent elsewhere (like implementing the performance-critical parts in another language). It’s hard to believe how slow Python is if you don’t have first-hand experience.

    I have written code for heuristically solving some hard problems; simulated annealing and tabu search, for instance. I would have expected Python to be something like 10x slower than C, but in my experience it’s not unrealistic for a (well written) Python implementation for the same algorithm to be 100-300x slower than the C implementation. I know this particularly because of my habit to prototype such programs in Python before writing them in C — an approach which I can wholeheartedly recommend to others, as I find that the total time to prototype in Python and write the final implementation in C is usually shorter than the time to go with C from the start. Python is very well suited for this kind of task.

    The problem with the thought of using threads in Python for performance is that the added complexity is nontrivial. A complex Python program (one that uses threads) can easily surpass the complexity of a single-threaded C/C++ program to solve the same problem, and the latter will still give you typically 25x the performance you could ever hope to get with a threaded Python implementation.

    As I see it, there are basically two reasons to use threads in a Python program, and for neither of them getting rid of the GIL is particularly critical:

    1. Threads are particularly well suited to some problems (i.e. some tasks are easier to do with threads than with, say, select())
    2. You want performance and you are prototyping for a threaded implementation in a lower level language

    Still my main use for Python is not prototyping but simple scripts, and I must say I’m really fairly happy with Python. Simple scripts and threads don’t mix anyway :)

    And to emphasize again, I’m not criticizing Python here. My friends tell me (but I do not have first hand experience) that Perl and Ruby are just as slow or even slower. Focusing on GIL removal on Python just feels to me like focusing on making the aerodynamics of a horse cart better; that effort would just be best spent elsewhere.

    • I think a killer app of multi threading is gaming. Synchronizing physics, graphics, gamestate and game logic is a great use case for threads. The first 2 are perfect to keep in C, the last 2 will be super fun to write in python. The python community is blind to threads partly because the people who would have used them left after hearing about the GIL.

      So now we have this chicken and egg discussion on if threads are important for python or not. Frankly I haven’t done enough attempts at checking how bad IPC is for writing computer games, so I’m not 100% confident that threads are that important. Though I am completely sure this issue makes python sound like a toy language.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s