Hi! I am trying out the new experimental jit feature. These are the following steps I have taken:
clone the repository
checkout branch 3.13
run ./configure --enable-experimental-jit --prefix=/usr/local/python3.13j
make altinstall
Start the interpreter: /usr/local/python3.13j/bin/python3.13
Then, inside the intepreter I test to se if the jit is working or not
Python 3.13.0rc1 (TIMESTAMP) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sysconfig
>>> "_Py_JIT" in sysconfig.get_config_var("PY_CORE_CFLAGS")
False
I followed all of your steps, and it seems to have built correctly for me. Do you mind sharing the value of sysconfig.get_config_var("PY_CORE_CFLAGS")? Here’s mine:
In particular, it would help to see the logs from your configure and make steps:
The configure step should have the line: checking for --enable-experimental-jit... -D_Py_TIER2=1 -D_Py_JIT
Most of the compile commands in the make step should have those two flags: -D_Py_TIER2=1 -D_Py_JIT
There should also be a banner printed at some point in the make command that looks something like this:
=================================================================
JIT support for aarch64-apple-darwin23.6.0 is still experimental!
Please report any issues you encounter.
=================================================================
Which is interesting, I can clearly see that it is there. But, "_Py_JIT" in sysconfig.get_config_var("PY_CORE_CFLAGS") still returns false. Which I got most confused from. Thanks for clearing it up!
Result from the logs looks okay also:
cat config.log | grep ‘checking for --enable-experimental-jit’
configure:8289: checking for --enable-experimental-jit
So I think that proves that the JIT is active. Do you have an example to show that the JIT is working in runtime? I tried for example running the following program from the same thread:
def f(a, b):
return a + b
f(1, 2)
a = 0
for i in range(100000000):
a += f(1, 2)
print(a)
Using pypy for example, runs this very fast. But, my experimental jit does not improve the computation of this. Any suggestions of what might be the problem? Or am I simply not testing the jit correctly?
I believe the experimental jit currently just setting up infrastructure for future improvements. So you probably shouldn’t expect any significant performance changes right now.
Maybe this shows some JIT effect, adjust number to see whether the effect increases or decreases:
import time
def workload_func():
def inner():
[y for y in [x for x in range(5000)]]
[inner() for x in range(50)]
def run():
def inner():
[workload_func() for x in range(10)]
return inner
def main():
# use fast local variable
local_func = run()
# Warm up?
[local_func() for x in range(100)]
t0 = time.perf_counter()
[local_func() for x in range(100)]
dt = time.perf_counter() - t0
print(f"Took {dt} seconds.")
if __name__ == '__main__':
main()
Weird, for this code I consistently get a 15% speedup with PYTHON_JIT=1 over PYTHON_JIT=0, and an even bigger increase in relative performance for a --enable-experimental-jit --enable-optimizations --with-lto build.
Could you please add checks for whether workload_func() and run() are JITted using the code below?
def is_jitted(f: types.FunctionType) -> bool:
for i in range(0, len(f.__code__.co_code), 2):
try:
print(f"Valid executor for {f.__name__}: {_opcode.get_executor(f.__code__, i).is_valid()}")
except RuntimeError:
# This isn't a JIT build:
return False
except ValueError:
# No executor found:
continue
return True
return False