Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set enable-experimental-jit=yes-off on Python 3.13 / Linux #538

Merged
merged 3 commits into from
Feb 27, 2025
Merged

Conversation

zanieb
Copy link
Member

@zanieb zanieb commented Feb 25, 2025

See #535

This builds the JIT, but disables it by default. Users can opt-in to enable it at runtime.

3.14 and macOS support will follow, there are some hiccups there.

@zanieb zanieb marked this pull request as draft February 25, 2025 02:15
@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

x86_64-apple-darwin / 3.14 / freethreaded+pgo+lto
x86_64-unknown-linux-gnu / 3.14 / freethreaded+pgo+lto
x86_64_v3-unknown-linux-gnu / 3.14 / freethreaded+pgo+lto

cpython-3.14> In file included from Python/ceval.c:781:
cpython-3.14> Python/generated_cases.c.h:4934:13: error: use of undeclared label 'error'
cpython-3.14>  4934 |             GOTO_TIER_TWO(executor);
cpython-3.14>       |             ^
cpython-3.14> Python/ceval_macros.h:398:14: note: expanded from macro 'GOTO_TIER_TWO'
cpython-3.14>   398 |         goto error;                                    \
cpython-3.14>       |              ^
cpython-3.14> In file included from Python/ceval.c:781:
cpython-3.14> Python/generated_cases.c.h:6968:25: error: use of undeclared label 'error'
cpython-3.14>  6968 |                         GOTO_TIER_TWO(executor);
cpython-3.14>       |                         ^
cpython-3.14> Python/ceval_macros.h:398:14: note: expanded from macro 'GOTO_TIER_TWO'
cpython-3.14>   398 |         goto error;                                    \
cpython-3.14>       |              ^
cpython-3.14> 2 errors generated.

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

aarch64-apple-darwin / 3.13 / freethreaded+pgo+lto
x86_64-unknown-linux-gnu / 3.13 / freethreaded+pgo+lto

cpython-3.13> 
cpython-3.13> ===========================================================
cpython-3.13> JIT support for ... is still experimental!
cpython-3.13>           Please report any issues you encounter.
cpython-3.13> ===========================================================
cpython-3.13> 
cpython-3.13>   + Exception Group Traceback (most recent call last):
cpython-3.13>   |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/./Tools/jit/build.py", line 28, in <module>
cpython-3.13>   |     args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force)
cpython-3.13>   |     ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cpython-3.13>   |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_targets.py", line 214, in build
cpython-3.13>   |     stencil_groups = asyncio.run(self._build_stencils())
cpython-3.13>   |   File "/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/tools/host/lib/python3.13/asyncio/runners.py", line 195, in run
cpython-3.13>   |     return runner.run(main)
cpython-3.13>   |            ~~~~~~~~~~^^^^^^
cpython-3.13>   |   File "/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/tools/host/lib/python3.13/asyncio/runners.py", line 118, in run
cpython-3.13>   |     return self._loop.run_until_complete(task)
cpython-3.13>   |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
cpython-3.13>   |   File "/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/tools/host/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
cpython-3.13>   |     return future.result()
cpython-3.13>   |            ~~~~~~~~~~~~~^^
cpython-3.13>   |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_targets.py", line 189, in _build_stencils
cpython-3.13>   |     async with asyncio.TaskGroup() as group:
cpython-3.13>   |                ~~~~~~~~~~~~~~~~~^^
cpython-3.13>   |   File "/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/tools/host/lib/python3.13/asyncio/taskgroups.py", line 71, in __aexit__
cpython-3.13>   |     return await self._aexit(et, exc)
cpython-3.13>   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
cpython-3.13>   |   File "/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/tools/host/lib/python3.13/asyncio/taskgroups.py", line 173, in _aexit
cpython-3.13>   |     raise BaseExceptionGroup(
cpython-3.13>   |     ...<2 lines>...
cpython-3.13>   |     ) from None
cpython-3.13>   | ExceptionGroup: unhandled errors in a TaskGroup (2 sub-exceptions)
cpython-3.13>   +-+---------------- 1 ----------------
cpython-3.13>     | Traceback (most recent call last):
cpython-3.13>     |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_targets.py", line 180, in _compile
cpython-3.13>     |     await _llvm.run("clang", args_o, echo=self.verbose)
cpython-3.13>     |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_llvm.py", line 99, in run
cpython-3.13>     |     raise RuntimeError(f"Can't find {tool}-{_LLVM_VERSION}!")
cpython-3.13>     | RuntimeError: Can't find clang-18!
cpython-3.13>     +---------------- 2 ----------------
cpython-3.13>     | Traceback (most recent call last):
cpython-3.13>     |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_targets.py", line 180, in _compile
cpython-3.13>     |     await _llvm.run("clang", args_o, echo=self.verbose)
cpython-3.13>     |   File "/private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmp9dae5lu8/Python-3.13.2/Tools/jit/_llvm.py", line 99, in run
cpython-3.13>     |     raise RuntimeError(f"Can't find {tool}-{_LLVM_VERSION}!")
cpython-3.13>     | RuntimeError: Can't find clang-18!
cpython-3.13>     +------------------------------------
cpython-3.13> make[2]: *** [jit_stencils.h] Error 1

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

Looks like 3.13 fails missing Clang 18 and 3.14 fails due to use of undeclared label.

@brandtbucher
Copy link

Thanks! To clarify, these are free-threading + JIT?

@brandtbucher
Copy link

I assume you can't use Clang 18 to build it on 3.13? As a quick hack, replacing _LLVM_VERSION = 18 with _LLVM_VERSION = 19 at the top of Tools/jit/_llvm.py will probably work. (We could maybe also backport a change to accept both versions if needed.)

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

All the failures I linked happened to be the free-threaded builds, but you can see non-freethreaded failures too.

I started copying failures then realized all of the relevant builds had failed.

I assume you can't use Clang 18 to build it on 3.13?

I think it'd be a pain to have a separate toolchain for it, yeah.

As a quick hack, replacing _LLVM_VERSION = 18 with _LLVM_VERSION = 19 at the top of Tools/jit/_llvm.py will probably work.

I'll try that. Thanks!

@zanieb zanieb added platform:darwin Specific to the macOS platform platform:linux Specific to the Linux platform labels Feb 26, 2025
@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

That got us to a new failure on macOS, e.g.,

aarch64-apple-darwin / 3.13 / pgo+lto
x86_64-apple-darwin / 3.13 / pgo+lto

cpython-3.13> In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13> In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13> In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <asserIn file included from In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:t19.:10: h>fatal error: 'assert.h' file not found
cpython-3.13>        19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13>            // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13> In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~
cpython-3.13> In file included from /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Tools/jit/template.c:1:
cpython-3.13> /private/var/folders/y4/8dcllrc96x32z0w3fgrlx6_m0000gn/T/tmpb39azrd3/Python-3.13.2/Include/Python.h:19:10: fatal error: 'assert.h' file not found
cpython-3.13>    19 | #include <assert.h>               // assert()
cpython-3.13>       |          ^~~~~~~~~~

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

But hey the 3.13 Linux jobs pass now!

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

I'd like to merge this so I'm going to turn the jit off on 3.14 and macOS — we can revisit those later.

@brandtbucher
Copy link

brandtbucher commented Feb 26, 2025

Weird. Are you using Apple Clang, or a separate LLVM install? It should be the latter.

The JIT files are compiled separately from the main build system. If you're modifying search paths in any way, you might have to add similar compiler options here: https://github.com/python/cpython/blob/fda056e64bdfcac3dd3d13eebda0a24994d83cb8/Tools/jit/_targets.py#L108-L144

Or, if they're target-specific, you can add them to the args keyword passed to the target when we construct it here: https://github.com/python/cpython/blob/fda056e64bdfcac3dd3d13eebda0a24994d83cb8/Tools/jit/_targets.py#L499-L526

@brandtbucher
Copy link

brandtbucher commented Feb 26, 2025

For the missing label, what tags are you building here (and what configure options)? Want to see if I can reproduce.

@brandtbucher
Copy link

Oh, it looks like you're also building the tail-calling interpreter too? That's likely the problem. You'll want to patch in https://github.com/python/cpython/pull/129820/files#diff-45baf725df91ed7826458cda8a17c2b4a2e5296504de1ed6a1c5a9ebe6390a47, where that was fixed. The JIT and tail-calling didn't work together before that.

@brandtbucher
Copy link

(But thanks for stress-testing us with your bleeding-edge free-threaded tail-calling JIT builds, haha.)

@zanieb
Copy link
Member Author

zanieb commented Feb 26, 2025

Thanks for following up!

I'll see if python/cpython#129820 fixes the 3.14 builds — I believe that addresses your missing label question.

Weird. Are you using Apple Clang, or a separate LLVM install? It should be the latter.

Separate.

"llvm-aarch64-macos": {
"url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-aarch64-apple-darwin.tar.zst",
"size": 143884729,
"sha256": "c0252c7ebe0b20125fe592a12d43a693fcab0bfa3bec9def6b96b97087e0f765",
"version": "19.1.6+20241231",
},
# Remember to update LLVM_URL in src/release.rs whenever upgrading.
"llvm-x86_64-macos": {
"url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-x86_64-apple-darwin.tar.zst",
"size": 143113277,
"sha256": "e990dea9ff89e4202d358b477a43f2bd128b244926534b7c8bb29feeaada994e",
"version": "19.1.6+20241231",
},

The JIT files are compiled separately from the main build system. If you're modifying search paths in any way, you might have to add similar compiler options here:

That's helpful! I'll look into the search paths and report back.

@zanieb zanieb marked this pull request as ready for review February 26, 2025 23:30
@zanieb zanieb changed the title Set enable-experimental-jit=yes-off on Python 3.13+ Set enable-experimental-jit=yes-off on Python 3.13 / Linux Feb 26, 2025
@zanieb
Copy link
Member Author

zanieb commented Feb 27, 2025

Tested on Linux

❯ ./python/install/bin/python3 loops.py
3.13.2 (main, Feb 26 2025, 23:10:54) [Clang 19.1.6 ]
Number of long_calcul per second: 13.48
❯ PYTHON_JIT=1  ./python/install/bin/python3 loops.py
3.13.2 (main, Feb 26 2025, 23:10:54) [Clang 19.1.6 ]
Number of long_calcul per second: 18.38

@brandtbucher
Copy link

Mind sharing loops.py?

@zanieb
Copy link
Member Author

zanieb commented Feb 27, 2025

@brandtbucher yeah np, just took this from the report asking for the feature as a quick test #535

import time
import sys


def short_calcul(n):
    result = 0
    for i in range(1, n+1):
        result += i
    return result


def long_calcul(num):
    result = 0
    for i in range(num):
        result += short_calcul(i) - short_calcul(i)
    return result


number = 1000
time_total = 8

for _ in range(10):
    long_calcul(number)

n_test = 10
assert short_calcul(n_test) == n_test * (n_test + 1) // 2
assert long_calcul(number) == 0

t_start = time.perf_counter()
long_calcul(number)
t_1_long_calcul = time.perf_counter() - t_start

number_long_calcul = int(time_total / t_1_long_calcul)


t_start = time.perf_counter()
for _ in range(number_long_calcul):
    long_calcul(number)
t_tot = time.perf_counter() - t_start

print(sys.version)
print(f"Number of long_calcul per second: {number_long_calcul/t_tot:.2f}")

Nothing special about it otherwise.

@zanieb zanieb merged commit d7759a1 into main Feb 27, 2025
39 checks passed
@zanieb zanieb deleted the zb/jit branch February 27, 2025 18:33
zanieb added a commit that referenced this pull request Feb 27, 2025
@harshil21
Copy link

Thanks for this feature! I noticed that this isn't available on arm64 linux. Are there any plans on building with this enabled on that platform?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build:pgo platform:darwin Specific to the macOS platform platform:linux Specific to the Linux platform python:3.13 python:3.14
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants