5 ms·
This post highlights an interesting dichotomy in the Python scientific computing community. Everyone knows that PyPy runs faster than CPython for many common t
by jboy 11y ago
This post highlights an interesting dichotomy in the Python scientific computing community. Everyone knows that PyPy runs faster than CPython for many common tasks [1].
[1] PyPy is on average 7x faster than CPython: http://speed.pypy.org/ http://speed.pypy.org/
But those in the Python community who are serious about scientific computing (or image processing, like my startup) are already using Numpy & Scipy, which provide hand-coded C implementations of most matrix-related operations. Everyone knows that Python for-loops are "slow" [2], and storing a large 2-D matrix as a list-of-list-of-Python-int-object would require a huge amount of memory & indirection. So, Numpy offers an N-dimensional array type, implemented in C: C arrays of densely-packed C primitive types, with for-loops in C to iterate over the matrix elements. Then Scipy builds a lot of Matlab-like functionality as modules on top of this fundamental Numpy array type.
[2] Python for-loops are slow: https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow/ https://jakevdp.github.io/blog/2014/05/09/why-python-is-slow...
So the most expensive operations in a Python number-crunching program are likely already implemented using Numpy & Scipy operations, which run in compiled C (and additionally, often make use of Blas/Atlas/LAPACK/etc, for even greater speedups in sustained number-crunching).
But unfortunately, Numpy & PyPy do not naturally work together. Being written in C, Numpy makes substantial use of the CPython C-API -- and in fact, Numpy provides its own C-API [3]! The official Numpy package doesn't work with PyPy; the PyPy project very thoughtfully provides its own PyPy-compatible Numpy package [4].
[3] Numpy C-API: http://docs.scipy.org/doc/numpy-1.10.0/reference/c-api.html http://docs.scipy.org/doc/numpy-1.10.0/reference/c-api.html
[4] PyPy-compatible Numpy package: http://pypy.org/download.html#installing-numpy http://pypy.org/download.html#installing-numpy
Furthermore, Numpy is fantastic, but it can't offer all possible permutations of matrix operations. In particular, there are certain image-processing operations that are awkward (and thus, computationally-inefficient) to express using Numpy operations. So you might ultimately need to go to the Numpy C-API anyway.
This is why we created (and, just a few days ago, open-sourced) Pymod: https://github.com/jboy/nim-pymod https://github.com/jboy/nim-pymod
Pymod is a Nim+Python project that auto-generates all the Python C-API boilerplate & auto-compiles a Python C extension module that wraps the functions in a Nim module. Pymod enables us to write our Numpy array-processing code in Nim, then compile it (for C++-like speeds) as a well-behaved Python module. Nim made this very easy, because it compiles to C.
After considering our Python-integration options (CPython C-API, `ctypes` and `cffi`), we decided to go with the CPython C-API & Numpy C-API. We explained this decision in greater detail in the "Implementation details" section of the Pymod README [5]; the executive summary is that `ctypes` seems better suited to wrapping C types in Python, rather than exposing existing Python types in C, while the CPython C-API code could be generated & compiled with the C code that Nim was going to produce anyway.
[5] Pymod implementation details: https://github.com/jboy/nim-pymod#implementation-details https://github.com/jboy/nim-pymod#implementation-details
That said, we would be delighted for Pymod-produced Python modules to be able to run under PyPy. We've been strongly considering implementing a `cffi` back-end for Pymod, but this won't necessarily solve the Numpy issue. It would be even better if PyPy could support all the CPython C-API extension modules in the world in one fell swoop.
- Animats 11y ago"Python for-loops are slow" CPython for-loops are slow. PyPy for-loops are not slow. A loop that just counts is about 25x faster in PyPy than in CPython, for large numbers of iterations.
- jboy 11y ago> CPython for-loops are slow. PyPy for-loops are not slow. I fear you might have missed the point of that paragraph. The point was that multiple reasons contributed to the need for Numpy, so now it exists and is widely used by those who are serious about their scientific computing. The vast majority of those reasons are still valid, even though PyPy speeds up some general-purpose programming tasks in Python. "A loop that just counts" is not anywhere near a substitute for Numpy. Nor does a 25x speed increase in a particular operation (from CPython to PyPy) hold a candle to the number-crunching speedups provided by algorithm-optimized, code-optimized (often to the point of targeting specific vector instruction sets like SSEx) special-purpose numeric libraries.
- p4wnc6 11y agoCan you comment on the difference between Pymod and Cython? Cython's pretty mature now and it's straight up amazing how easy it is to generate cross-platform extension modules. It even exposes a lot of C++ too. Cython is a separate programming language that allows you to write C code with a special Python-like syntax, or write Python with Python syntax (including NumPy), and has a few extra type annotation bits here and there (like array syntax or pointer syntax). At the end, it creates the equivalent C code (with all needed CPython API boilerplate) and compiles it into an importable shared object file. Just from the description above, it sounds superficially the same as Pymod; is it fair to say Pymod is to Nim what Cython is to C/C++? I'd be very interested to know more about how the two tools compare and contrast.
- jboy 11y agoSure, this is a question that people ask quite frequently. I most recently answered it here: https://news.ycombinator.com/item?id=10569768 https://news.ycombinator.com/item?id=10569768 """Actually, Pymod was designed to be almost an anti-Cython. :) My issue with Cython is that it's a limited sub-language within Python, where you add Cython elements incrementally & iteratively (diverging from Python in the process) until the code runs "fast enough". I'd rather work directly in a full-featured, internally-self-consistent language from the start. Nim has a clean Pythonic syntax, with all the best parts of C++ (including its runtime speed). Hence, Pymod takes the form of an `exportpy` annotation (a user-defined Nim pragma) onto existing Nim functions, which are then auto-compiled into a Python extension module. So there's no gradual divergence of my Python code (as it becomes more "Cythonized"); rather, the high-performance code is written directly in pure Nim. :) """ There are a few more details in that thread comparing the wrapping of existing C libraries in Cython vs Pymod. (It doesn't seem right to copy-paste an entire thread...)