Live data from Hacker News

Making Python fast – Adventures with mypyc

blog.meadsteve.dev

51–60 of 95 posts

Re: Making Python fast – Adventures with mypyc

#51
I’ll be that guy who says I love Python but it’s been shoved into too many spaces now. It’s been a great tool for me for writing things that require a lot of I/O and aren’t CPU bound.

I am even rethinking that now because I was able to write a program in Go with an HTTP API and using JSON as the usual API interchange format in one night (all stdlib too), and it was so easy that I plan to pitch using it for several services we need to rewrite at work that are currently in Python. That would be very similar to what I wrote in a day.

If Python doesn’t fix their packaging, performance, and the massive expansion in the language, I think it’s going to start losing ground to other languages.

Re: Making Python fast – Adventures with mypyc

#52

Earlier quoted context omitted.

What things are you thinking of? (Not trying to interrogate you or prove you wrong, but I've got an interest in optimising very difficult meta-programming patterns.)

Nearly everything (or is it everything?) in memory can be modified at runtime. There are no real constants for example. The whole stack top to bottom can be monkeypatched on a whim. This means nothing is guaranteed and so every instruction must do multiple checks to make sure data structures are what is expected at the current moment. This is true of JS as well, but to a lesser extent.

> so every instruction must do multiple checks

Aren't all the things you mentioned already fixed by deoptimisation?

You assume constants cannot be modified, and then get the code that wants to modify constants to do the work of stopping everyone who is assuming a constant value, and modify them that they need to pick up the new value?

> To deoptimize means to jump from more optimised code to less optimized code. In practice that usually means to jump from just-in-time compiled machine code back into an interpreter. If we can do this at any point, and if we can perfectly restore the entire state of the interpreter, then we can start to throw away those checks in our optimized code, and instead we can deoptimize when the check would fail.

https://chrisseaton.com/truffleruby/deoptimizing/

I work on a compiler for Ruby, and mutable constants and the ability to monkey patch etc adds literally zero extra checks to optimised code.

Re: Making Python fast – Adventures with mypyc

#53

Earlier quoted context omitted.

Right, but I think we know how to optimise all these things. It's all solved problems.

A few things are impossible without changing/subsetting the language. What I was trying to get at.

I think it's more that cpython is so slow so a lot of things people use are implemented using the C API, and many optimizations will break a bunch of things. If everything was pure python the situation would be different.

Re: Making Python fast – Adventures with mypyc

#54

Earlier quoted context omitted.

Nearly everything (or is it everything?) in memory can be modified at runtime. There are no real constants for example. The whole stack top to bottom can be monkeypatched on a whim. This means nothing is guaranteed and so every instruction must do multiple checks to make sure data structures are what is expected at the current moment. This is true of JS as well, but to a lesser extent.

> so every instruction must do multiple checks Aren't all the things you mentioned already fixed by deoptimisation? You assume constants cannot be modified, and then get the code that wants to modify constants to do the work of stopping everyone who is assuming a constant value, and modify them that they need to pick up the new value? > To deoptimize means to jump from more optimised code to less optimized code. In p…

No such thing as a constant in Python. You can optionally name a variable in uppercase to signal to others that it should be, but that's about it.

You can write a new compiler if you'd like, as detailed on this page. But CPython doesn't work that way and 99% of the ecosystem is targeted there.

There is some work on making more assumptions as it runs, now that the project has funding. This is about where my off-top-of-head knowledge ends however so someone else will want to chime in here. The HN search probably has a few blog posts and discussions as well.

Re: Making Python fast – Adventures with mypyc

#55

Earlier quoted context omitted.

> so every instruction must do multiple checks Aren't all the things you mentioned already fixed by deoptimisation? You assume constants cannot be modified, and then get the code that wants to modify constants to do the work of stopping everyone who is assuming a constant value, and modify them that they need to pick up the new value? > To deoptimize means to jump from more optimised code to less optimized code. In p…

No such thing as a constant in Python. You can optionally name a variable in uppercase to signal to others that it should be, but that's about it. You can write a new compiler if you'd like, as detailed on this page. But CPython doesn't work that way and 99% of the ecosystem is targeted there. There is some work on making more assumptions as it runs, now that the project has funding. This is about where my off-top-of…

> No such thing as a constant in Python. You can optionally name a variable in uppercase to signal to others that it should be, but that's about it.

Yeah that’s the point - the JIT takes that capitalisation as a hint to treat it as a true constant and bake the value in until it’s redefined.

This is all solved stuff and isn’t a barrier to implementing a powerful JIT for Python if someone wanted to.

Re: Making Python fast – Adventures with mypyc

#56

Speaking of python performance, I recently benchmarked "numpy vs js" matrix multiplication performance, and was surprised to find js significantly outperforming numpy. For multiplying two 512x512 matrices: python numpy: ~3.30ms numpy with numba: ~2.90ms node tfjs: ~1.00ms gpu.js: ~4.00ms ndarray: ~118.00ms vanilla loop: ~138.00ms mathjs: ~1876.00ms browser tfjs webgpu: ~.16ms tfjs webgl: ~.76ms tfjs wasm: ~2.51ms gpu…

Numpy runs on CPU. Tfjs runs on GPU. Not a fair comparison.

Re: Making Python fast – Adventures with mypyc

#57
post #41

Earlier quoted context omitted.

so you'd call the pre-JIT JVM an "interpreter" and you'd call Java an interpreted language?

> so you'd call the pre-JIT JVM an "interpreter" Yeah? I think almost everyone would? > and you'd call Java an interpreted language? Java is interpreted in many ways, and compiled in many ways, as I said it's complicated. It's compiled to bytecode, which is interpreted until it's time to be compiled... at which point it's abstract interpreted to a graph, which is compiled to machine code, until it needs to deoptimise…

I am not too concerned about the word "interpreter", and more about cPython being called an "interpreted language", which implies it works like Perl 5, or that cPython being an "interpreter" is somehow a problem. It's normal mode of operation works more like pre-JVM Java, with "interpreted bytecode" from .pyc files.

Re: Making Python fast – Adventures with mypyc

#58
post #57

Earlier quoted context omitted.

> so you'd call the pre-JIT JVM an "interpreter" Yeah? I think almost everyone would? > and you'd call Java an interpreted language? Java is interpreted in many ways, and compiled in many ways, as I said it's complicated. It's compiled to bytecode, which is interpreted until it's time to be compiled... at which point it's abstract interpreted to a graph, which is compiled to machine code, until it needs to deoptimise…

I am not too concerned about the word "interpreter", and more about cPython being called an "interpreted language", which implies it works like Perl 5, or that cPython being an "interpreter" is somehow a problem. It's normal mode of operation works more like pre-JVM Java, with "interpreted bytecode" from .pyc files.

Most people don’t make this distinction, and would just say ‘interpreter’. Interpreting bytecode vs an AST is a pretty minor difference. It’s exactly the same data in a slightly different format. The ‘compilation’ is just a post-order linearisation. And storing it in files or not even more so.

Re: Making Python fast – Adventures with mypyc

#59

Speaking of python performance, I recently benchmarked "numpy vs js" matrix multiplication performance, and was surprised to find js significantly outperforming numpy. For multiplying two 512x512 matrices: python numpy: ~3.30ms numpy with numba: ~2.90ms node tfjs: ~1.00ms gpu.js: ~4.00ms ndarray: ~118.00ms vanilla loop: ~138.00ms mathjs: ~1876.00ms browser tfjs webgpu: ~.16ms tfjs webgl: ~.76ms tfjs wasm: ~2.51ms gpu…

Numpy runs on CPU. Tfjs runs on GPU. Not a fair comparison.

You're right, it's not a fair comparison -- I think it's still interesting though, since numpy is the standard people would reach for, which made me think it would be the fastest / use the GPU. I expect a python library that uses the GPU would be just as fast as the others.

Re: Making Python fast – Adventures with mypyc

#60
post #57

Earlier quoted context omitted.

I am not too concerned about the word "interpreter", and more about cPython being called an "interpreted language", which implies it works like Perl 5, or that cPython being an "interpreter" is somehow a problem. It's normal mode of operation works more like pre-JVM Java, with "interpreted bytecode" from .pyc files.

Most people don’t make this distinction, and would just say ‘interpreter’. Interpreting bytecode vs an AST is a pretty minor difference. It’s exactly the same data in a slightly different format. The ‘compilation’ is just a post-order linearisation. And storing it in files or not even more so.

as I'm sure you're aware, bytecode interpretation typically implies a superior performing model than AST interpretation, and compiling into bytecode produces a lot of opportunities for optimization that are not typically feasible when working with an AST directly. Of course it's all bits and anything is possible, but it's assumed to be a better approach in a generally non-subtle way.
Post reply on HN