Live data from Hacker News

State of Python 3.13 performance: Free-threading

codspeed.io

141–150 of 193 posts

Re: State of Python 3.13 performance: Free-threading

#141
post #47

If it were ever open sourced, I could see Mojo filling the performance niche for Python programmers. I'm hopeful because Lattner certainly has the track record, if he doesn't move on beforehand. https://en.wikipedia.org/wiki/Mojo_(programming_language)

If not, Nim is probably the closest most 'Python-like' language that is almost as fast as C, and is released under the MIT licence.

https://nim-lang.org/

https://en.wikipedia.org/wiki/Nim_(programming_language)

Re: State of Python 3.13 performance: Free-threading

#142

I don't really have a dog in this race as I don't use Python much, but this sort of thing always seemed to be of questionable utility to me. Python is never really going to be 'fast' no matter what is done to it because its semantics make most important optimizations impossible, so high performance "python" is actually going to always rely on restricted subsets of the language that don't actually match language's "re…

The IPC overhead of process-based parallelism in Python is a pain to deal with in general, even when the underlying computational bottleneck are already written CPU optimized (calls to compiled extensions written in Cython/C/C++/Rust, call to CPU optimized operations written with CPU architecture-specific intrinsics/assembly from OpenBLAS via NumPy/SciPy, calls to e.g. GPU CUDA kernels via PyTorch/Triton, ...).

Sometimes the optimal level of parallelism lies in an outer loop written in Python instead of just relying on the parallelism opportunities of the inner calls written using hardware specific native libraries. Free-threading Python makes it possible to choose which level of parallelism is best for a given workload without having to rewrite everything in a low-level programming language.

Re: State of Python 3.13 performance: Free-threading

#143
post #25

[flagged]

> people are kept in line with CoC threats Can you point to an example of someone claiming that a particular feature's performance claims were misleading, and then getting threatened with a ban or other sanctions for it, where they did not otherwise violate CoC?

> where they did not otherwise violate CoC?

Violations are in the eye of the enforcer.

Re: State of Python 3.13 performance: Free-threading

#144
post #31
post #24

Earlier quoted context omitted.

There was a discussion the other day about how Python devs apparently don't care enough for backwards compatibility. I pointed out that I've often gotten Python 2 code running on Python 3 by just changing print to print(). But then a few hours later, I tried running a very small project I wrote last year and it turned out that a bunch of my dependencies had changed their APIs. I've had similar (and much worse) experi…

So pin your deps? Language backwards compatibility and an API from some random package changing are completely distinct.

Yes and no.

There are different types of dependencies, and there are different rules for them, but here's an overview of the best practices:

1. For applications, scripts and services (i.e. "executable code"), during development, pin your direct dependencies; ideally to the current major or minor version, depending how much you trust their their authors to follow SemVer. Also make sure you regularly update and retest the versions to make sure you don't miss any critical updates.

You should not explicitly pin your transitive dependencies, i.e. the dependencies of your direct dependencies -- at least unless you know specifically that certain versions will break your app (and even then it is better to provide a range than a single version).

2. For production builds of the above, lock each of your dependencies (including the transitive ones) to specific version and source. It is not really viable to do it by hand, but most packaging tools -- pip, Poetry, PDM, uv... -- will happily do that automatically for you. Unfortunately, Python still doesn't have a standard lock format, so most tools provide their own lock file; the closest thing to a standard we have at the moment is pip's requirements file [0].

Besides pinned versions, a lock file will also include the source where the packages are to be retrieved from (pip's requirements file may omit it, but it's then implicitly assumed to be PyPI); it can (and should, really) also provide hashes for the given packages, strengthening the confidence that you're downloading the correct packages.

3. Finally, when developing libraries (i.e. "redistributable code"), you should never pin your dependencies at all -- or, at most, you can specify the minimum versions that you know that work and have tested against. That is because you have no control over the environment the code will eventually be used and executed in, and arbitrary limitations like that might (and often will) prevent your users to update some other crucial dependency.

Of course, the above does not apply if you know that a certain version range will break your code. It that case you should most definitely exclude it from your specification -- but you should also update your code as soon as possible. Libraries should also clearly specify which versions of Python they support, and should be regularly tested against each of those versions; it is also recommended that the minimal supported version is regularly reviewed and increased as new versions of Python get released [1].

For more clarity on abstract vs concrete dependencies, I recommend the great article by Donald Stufft from 2013 [2]; and for understanding why top-binding (i.e. limiting the top version pin) should be avoided there is a lengthy but very detailed analysis by Henry Schreiner [3].

[0] https://pip.pypa.io/en/stable/reference/requirements-file-fo...

[1] https://devguide.python.org/versions/

[2] https://caremad.io/posts/2013/07/setup-vs-requirement/

[3] https://iscinumpy.dev/post/bound-version-constraints/

Re: State of Python 3.13 performance: Free-threading

#145

Can someone share insight into what was technically done to enable this? What replaced the global lock? Is the GC stopping all threads during collection or an other locking mechanism?

AFAIK the initial prototype called nogil was developed by a person named Sam Gross who also wrote a detailed article [0] about it.

He also had a meeting with Python core. Notes from this meeting [1] by Łukasz Langa provide more high-level overview, so I think that they are a good starting point.

[0] https://docs.google.com/document/u/0/d/18CXhDb1ygxg-YXNBJNzf...

[1] https://lukasz.langa.pl/5d044f91-49c1-4170-aed1-62b6763e6ad0...

Re: State of Python 3.13 performance: Free-threading

#146

I don't really have a dog in this race as I don't use Python much, but this sort of thing always seemed to be of questionable utility to me. Python is never really going to be 'fast' no matter what is done to it because its semantics make most important optimizations impossible, so high performance "python" is actually going to always rely on restricted subsets of the language that don't actually match language's "re…

Even if something is slow there is utility to have it run faster. Sure, Python will never be with for the most demanding performance requirements but that doesn't mean we should deny people performance.

There are lots of use case where Python's performance is acceptable but a 10x speed boost would be much appreciated. Or where Python's performance is not acceptable but it would be if I could fully utilize my 32 cores.

For example look at Instagram. They run tons of Python but need to run many processes on each machine wasting memory. I'm sure they would love to save that memory, the environment would too. Sure, they could rewrite their service in C but that is most likely not the best tradeoff.

Re: State of Python 3.13 performance: Free-threading

#147

Can someone share insight into what was technically done to enable this? What replaced the global lock? Is the GC stopping all threads during collection or an other locking mechanism?

The most interesting idea in my opinion is biased reference counting [0].

An oversimplified explanation (and maybe wrong) of it goes like this:

problem:

- each object needs a reference counter, because of how memory management in Python works

- we cannot modify ref counters concurrently because it will lead to incorrect results

- we cannot make each ref counter atomic because atomic operations have too large performance overhead

therefore, we need GIL.

Solution, proposed in [0]:

- let's have two ref counters for each object, one is normal, another one is atomic

- normal ref counter counts references created from the same thread where the object was originally created, atomic counts references from other threads

- because of an empirical observation that objects are mostly accessed from the same thread that created them, it allows us to avoid paying atomic operations penalty most of the time

Anyway, that's what I understood from the articles/papers. See my other comment [1] for the links to write-ups by people who actually know what they're talking about.

[0] https://dl.acm.org/doi/10.1145/3243176.3243195

[1] https://news.ycombinator.com/item?id=42059605

Re: State of Python 3.13 performance: Free-threading

#148

I don't really have a dog in this race as I don't use Python much, but this sort of thing always seemed to be of questionable utility to me. Python is never really going to be 'fast' no matter what is done to it because its semantics make most important optimizations impossible, so high performance "python" is actually going to always rely on restricted subsets of the language that don't actually match language's "re…

I am always wondering who writes code so badly unaware of concurrency issues, to rely on the GIL. Wondering how many libraries and programs will actually break. But probably the number is way higher than even I imagine.

Re: State of Python 3.13 performance: Free-threading

#149

Earlier quoted context omitted.

When they suggest you pin your dependencies, they don't just mean your direct dependencies, but rather all transitive dependencies. You can take this further by having a lock file that account for different Python versions, operating systems, and CPI architectures – for instance , by using UV or Poetry – but a simple `pip freeze` is often sufficient.

That works for your project, but then nobody can include you as a library without conflicts. But having that lock file will allow somebody to reconstruct your particular moment in time in the future. Its just that those lock files do not exist for 99.9% of Python projects in time.

A lib can still lock its dependencies and have version ranges declared at the same time. The lock file is an artifact than is used to reproducibly build the lib, while the version ranges are used to see, whether some other project can use the lib.

It is only a matter of tooling. Locking ones dependencies remains the right thing to do, even for a lib.

Re: State of Python 3.13 performance: Free-threading

#150
post #71

Earlier quoted context omitted.

Pinning deps is discouraged by years of Python practice. And going back to a an old project and finding versions that work, a year or more later, might be nigh on impossible. Last week I was trying to install snakemake via Conda, and couldn't find any way to satisfy dependencies at all, so it's not just pypi, and pip tends to be one of the more forgiving version dependency managers. It's not just Python, trying to ge…

It took me few days to get some old Jupyter Notebooks working. I had to find the correct older version of Jupyter, correct version of the every plugin/extension that notebook used and then I had to find the correct version of every dependency of these extensions. Only way to get it working was a bunch of pinned dependencies.

Had they been properly pinned before, you would not have had to work for a few days. Code in a Jupyter notebook is unlikely to be relied upon elsewhere. Perfectly good for making it always use the exact same versions (checked by checksums, whatever tool you are using).
Post reply on HN