Hello. I'm the author of the PR that landed the tail-calling interpreter in CPython. First, I want to say thank you to Nelson for spending almost a month to get to the root of this issue. Secondly, I want to say I'm extremely embarrassed and sorry that I made such a huge oversight. I, and probably the rest of the CPython team did not expect the compiler we were using for the baseline to have that bug. I posted an apo…
Performance of the Python 3.14 tail-call interpreter
81–90 of 180 posts
Re: Performance of the Python 3.14 tail-call interpreter
#82Earlier quoted context omitted.
One question arises: does the added code [1] bring any improvement, or does it merely complicate the source? Should it not be removed? [1] https://github.com/python/cpython/pull/128718
That's a fair question. The blog post mentions it brings a 1-5% perf improvement. Which is still significant for CPython. It does not complicate the source because we use a DSL to generate CPython's interpreters. So the only complexity is in autogenerated code, which is usually meant for machine consumption anyways. The other benefit (for us maintainers I guess), is that it compiles way faster and is more debuggable…
Several releases in, have we seen even a 2x speedup? Or more like 0.2x at best?
Not trying to dismiss the interpreter changes - more want to know if those speedup plans were even remotely realistic, and if anything close enough to even 1/5 of what was promised will really come out of them...
Re: Performance of the Python 3.14 tail-call interpreter
#83Earlier quoted context omitted.
Why would you want it to increment 1 if we decrement 1 from the same variable? That would be a waste of cycles and a good compiler knows how to optimize it out, or what am I misunderstanding here? What do you expect "it" to do and what does it really do? See: https://news.ycombinator.com/item?id=43320495
I'm pretty sure that's replying directly to the comment about how c is close to assembly and that if you add that line of code somewhere you know there's a variable getting incremented. Doesn't really matter whether or not it's useful, the point is that the behavior isn't exactly what you wrote
I linked these in another comment, but here's some examples of straightforward-looking integer addition emitting more complex compiler output for other languages that compile to native code:
Haskell: https://godbolt.org/z/vdeMKMETT
Re: Performance of the Python 3.14 tail-call interpreter
#84Hello. I'm the author of the PR that landed the tail-calling interpreter in CPython. First, I want to say thank you to Nelson for spending almost a month to get to the root of this issue. Secondly, I want to say I'm extremely embarrassed and sorry that I made such a huge oversight. I, and probably the rest of the CPython team did not expect the compiler we were using for the baseline to have that bug. I posted an apo…
Re: Performance of the Python 3.14 tail-call interpreter
#85Hello. I'm the author of the PR that landed the tail-calling interpreter in CPython. First, I want to say thank you to Nelson for spending almost a month to get to the root of this issue. Secondly, I want to say I'm extremely embarrassed and sorry that I made such a huge oversight. I, and probably the rest of the CPython team did not expect the compiler we were using for the baseline to have that bug. I posted an apo…
Re: Performance of the Python 3.14 tail-call interpreter
#86Earlier quoted context omitted.
It means that "a += 1` is easy to understand as incrementing a numeric value by 1" is not true and instead "it can be really difficult to map between the original source and the machine code". More examples of non-trivial mapping from C code to generated code: https://godbolt.org/z/jab6vh6dM
All of those look pretty straightforward to me -- again, what assembly would you expect to be emitted in those cases? For contrast, here's the assembly generated for Haskell for integer addition: https://godbolt.org/z/vdeMKMETT And here's assembly for C++: https://godbolt.org/z/dedcof9x5
It is very straightforward indeed, but it is still not mapping primitive operations to direct machine code, but it is forwarding to out-of-line code. Same as operator overloading in other languages.
> And here's assembly for C++: https://godbolt.org/z/dedcof9x5
That's just a symptom of allowing the compiler to inline the add code, otherwise the generated code is as straightforward:
addOne(Int):
push rax
mov esi,0x1
call 4010c0
Ref: https://godbolt.org/z/xo1es9TcWRe: Performance of the Python 3.14 tail-call interpreter
#87Earlier quoted context omitted.
C might be low level from the perspective of other systems languages, but that is like calling Apollo 11 simple from the perspective of modern spacecraft. C as written is not all that close to what actually gets executed. For a small example, there are many compilers who would absolutely skip incrementing 'a' in the following code: uint32_t add_and_subtract_1(uint32_t a) { a += 1; a -= 1; return a; } Even though that…
Why would you want it to increment 1 if we decrement 1 from the same variable? That would be a waste of cycles and a good compiler knows how to optimize it out, or what am I misunderstanding here? What do you expect "it" to do and what does it really do? See: https://news.ycombinator.com/item?id=43320495
Re: Performance of the Python 3.14 tail-call interpreter
#88Earlier quoted context omitted.
The parent example can be made clearer like this: https://godbolt.org/z/MKWbz9W16 Dead code elimination only works here because integer overflow is UB.
Take a closer look at 'eru's example and my follow-up. He wrote an example where the result of `a+1` isn't necessary, so the compiler doesn't emit an ADDI even though the literal text of the C source contains the substring "a += 1". Your version has the same issue: unsigned int square2(unsigned int num) { unsigned int a = num; a += 1; if (num The return value doesn't depend on `a+1`, so the compiler can optimize it t…
if (num
A control dependency is still a dependencyRe: Performance of the Python 3.14 tail-call interpreter
#89This is exactly the kind of content I love to see on HN. But I wonder though how this optimization is related to tail-call optimization? How the interpreter jump table is implemented shouldn't affect how stack frames are created, should it?
"A new type of interpreter has been added to CPython. It uses tail calls between small C functions that implement individual Python opcodes, rather than one large C case statement."
[0] https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-...
Re: Performance of the Python 3.14 tail-call interpreter
#90Hello. I'm the author of the PR that landed the tail-calling interpreter in CPython. First, I want to say thank you to Nelson for spending almost a month to get to the root of this issue. Secondly, I want to say I'm extremely embarrassed and sorry that I made such a huge oversight. I, and probably the rest of the CPython team did not expect the compiler we were using for the baseline to have that bug. I posted an apo…