6 ms·
I was sad that Cython was only given a fleeting nod at the end and numba wasn’t even mentioned. I might even go so far as to say that Cython is the most user-fr
by mlthoughts2018 8y ago
I was sad that Cython was only given a fleeting nod at the end and numba wasn’t even mentioned. I might even go so far as to say that Cython is the most user-friendly way to write new pure C programs that there is. If you’re about to write some greenfield project in C, seriously consider using Cython, even if you have no desire for any Python entrypoints in the final product. Numba as well is quite impressive: between jitclass, deferred_type, and facilities to target GPUs, it’s crazy how much speedup you can get with little extra code.
Overall I think people don’t clearly state the speed trade-off Python presents. Everyone focuses on the “40 times slower” part and nobody points out that “equivalent program in C++” is a glib false equivalence, because a truly equivalent program would have to offer all the same run-time dynamic type manipulation and nearly arbitrarily modifiable object instances involved.
What Python really proposes is this: “I’ll give you 100x more flexibility in exchange for 40x worse performance for certain classes of operations.”
Don’t want the 40x slowdown? Das cool. Code around it by using extension modules that let you specify homogeneously typed contiguous memory arrays (or bare metal structs like with ctypes or numba’s jitclass), or let you bypass CPython overhead because e.g. you know you don’t need the flexibility offered by the data model looking up a generic python function to call for an __add__ operation, and instead you can arrange for a GIL-releasing call to a pure C function. And so on.
I guess my point is that the story should be “look what Python gives you” and then “this flexibility had a cost.”
But instead it always feels more like, “this C pseudocode for this tight algorithm looks superficially similar to Python syntax for that algorithm ... but oh boy look how much slower Python is!” —- which, apart from a possible surprise when you have never looked into Python before, should be of interest to badically no one.
- SlowRobotAhead 8y agoThat’s certainly a fair way to put it. I guess I don’t encounter the type who really get upset that ”Python is too slow!! I’d rather use C++” because that takes a certain type of person who is technically able but practically challenged. I personally find myself surrounded by the opposite peoples.
- mlthoughts2018 8y agoThis is the beauty of Cython & numba for me. It lets you selectively target just the small sections of the code that need a speed-up for an understood reason. You can use nice Python profiling tools to gather evidence about which program hotspots truly are too slow, and then just target those for specialization either as extension module functions/classes in Cython (or even a manually written extension module, or a plain C library used via cffi), or as a JIT function or class with numba. You can use the annotation features of Cython & numba to further profile locations that have avoidable CPython API overhead, and it becomes a very evidence-based and iterative optimization cycle. At the end, for 90% of the Python code that was more than fast enough already and didn’t touch performance critical sections, you just got to save all the time & trouble of needing to rewrite it (usually painfully) and debug it and re-test it all in C or C++. This is why, for me, the entire idea that you should start a project out in C++ or C is a giant type of premature optimization in a lot of cases (not all cases but a lot). Did you prototype the boilerplate parts in Python and actually measure the sort of performance hotspots you’ll have to optimize, to a degree that you know for sure that some light sprinkling of Cython & numba certainly won’t work? If not, it’s probably premature optimization to presume you’ll need C or C++ as the primary implementation language.
- SlowRobotAhead 8y agoI use C day in day out for embedded. So you’ll get no complaints from me! What I’ll find interesting is if the CPyrhon idea is ever pushed to embedded. Because right now the state of microPython or Zerynth trying to be a one stop shops for micros but in Python isn’t attractive. Then again, I don’t want or need pythons standard libs - what I really want is all C code with an option to ultra lightweight run scripting in Python. So 90% C, 10% Py. No option exists yet.
- AlexCoventry 8y agoLua sounds like a good fit.
- 8y ago
- srean 8y ago> I might even go so far as to say that Cython is the most user-friendly way to write new pure C programs that there is. Apart from my vehement disagreement with the claim above I am in violent agreement with the rest of you comment. If I want_to / need_to write C or C++ I would rather write it in, well, C or C++. The reasons are many -- more mature tooling, deeper social knowledge, one less source of undocumented or unintended edge cases etc., etc. But when I want to be in a Pythonic frame of mind, which is fairly often, and want to freeze the semantics of selected parts of the code to a C or C++ like statically typed semantics, Cython is really nice. With Cython I can choose to do this where I think the code will benefit from freezing the semantics. Often I dont have to rely too hard on my own thinking because the Cython compiler would identify those sections for me.
- mncharity 8y agoThis seems a long-standing problem. Even with very early Python, it was possible to have objects providing an API of C pointers, to be dynamically combined with other such objects, to create runtime assemblages of C code, with only C's dynamically-linked function call overhead between the parts. And with cached runtime invocation of gcc and dynamic loading, it was possible for objects to provide C macro apis, and combine them into runtime-specialized fully-optimized code. But the approach didn't catch on. The community built C monoliths. Often multiple semi-abandoned monoliths with heavy feature overlap, but never code sharing. And then Windows slowly became important, with its lack of compiler access. So the problem seemed a social one, rather than technical. Far fewer people using python, and not enough of them cared about such things to achieve critical mass. And so the approach never matured or gained momentum. Was never embraced as "pythonic". In an alternate timeline, we did such very neat stuff with it. :/
- mncharity 8y agoERRATA: The assemblages created from objects carrying C pointers had only C function pointer call overhead (of course). It was different scheme, playing linker games, that had GOT overhead. And "multiple semi-abandoned monoliths with heavy feature overlap, but never code sharing" missed a key characteristic - the monoliths were all very partial solutions. So a common dynamic was "I need feature X, as in monolith A, and feature Y, as in monolith B, so... I'll create a new monolithic library C, with those features, but missing others from A and B that I don't care about". Leaving the next person in the same unhappy place, and scattering the little effort available into even smaller communities.
- dkersten 8y ago> a truly equivalent program would have to offer all the same run-time dynamic type manipulation and nearly arbitrarily modifiable object instances involved. In actual production code, I rarely need this though. I mean, sure, for framework code, but in C++ I can do quite a lot with the standard library and templates. Sure it’s not so runtime flexible as Python, but for normal production code, I’ve rarely found it necessary. Don’t get me wrong, I absolutely prefer Python for most of the use cases that it’s conmonly used for, but I don’t agree quite agree that the quoted text above matters for most uses. > What Python really proposes is this: “I’ll give you 100x more flexibility in exchange for 40x worse performance for certain classes of operations.” Have you used a recent version of C++? I think the 100x might have been true 15 years ago, but, while Python has a lot, lot more runtime flexibility, modern C++ is a pretty productive environment, without sacrificing performance. I’m not arguing that Python isn’t more flexible, especially at runtime, or that it’s not more productive. Of course it is. But you’re paying a performance premium for it and I don’t think the productivity gap is as large as the performance gap anymore. With all that said, I do agree with your overall message. Python gives you productivity and flexibility and it’s important to focus on that rather than performance and, as you say, Cython gives you options when you do need performance. But the difference between Python and C++ nowadays, for normal production code, isn’t that huge anymore in my opinion. Of course, there are plenty of reasons to prefer Python though: fantastic web frameworks and batteries included libraries, fantastic community, fantastic documentation to name a few.
- mlthoughts2018 8y agoI won’t be able to address all the points. But in my experience, C++ has been going in the wrong direction in terms of simplicity or productivity. Modern C++ is drastically more complicated and riddled with deep esoterica. The flexibility benefit modern Python gives is probably more like 1000x, further mitigating many cases when there are concerns about the flexibility/performance trade-off. Just for one example about what I mean with modern C++: < https://bitbashing.io/std-visit.html https://bitbashing.io/std-visit.html >. This example is relevant because you mentioned you feel you never need Python’s flexibility in the day to day. But in Python (much like in many functional languages), the entire idea of the visitor pattern can be boiled down to map() —- just one function call! If you want to specialize this for your own data type, you can very easily implement the iterator protocol, often simple __iter__, __getitem__, and __next__, which themselves could use e.g. numba to iterate some homogeneously typed tree class with pure C performance characteristics, or a sum type (like with Cython fused types) as in the std::visit example, etc. The point is that the data model’s flexibility makes this trivial, rather than convoluted. In the cases when I’d care about this pattern, it would be no contest that Python offers hugely improved productivity. So it’s not just naive flexibilty of modifying object instances, but the bigger picture of flexibility in the data model overall.
- jlarocco 8y ago> Overall I think people don’t clearly state the speed trade-off Python presents. Everyone focuses on the “40 times slower” part and nobody points out that “equivalent program in C++” is a glib false equivalence, because a truly equivalent program would have to offer all the same run-time dynamic type manipulation and nearly arbitrarily modifiable object instances involved. Unfortunately, Python doesn't do well by that standard, either. For a few years now I've switched to Common Lisp for all of my small projects, and IME it's 20-30 times faster than Python by default, and more dynamic and flexible. Declare types and turn on optimizations, and it's more like 30-40 times faster, though still generally a little slower than C or C++. And then it also can access C and Fortran libraries to speed things up further. I like Python, it's my second favorite language, but it's not perfect.
- coldtea 8y ago>Overall I think people don’t clearly state the speed trade-off Python presents. Everyone focuses on the “40 times slower” part and nobody points out that “equivalent program in C++” is a glib false equivalence, because a truly equivalent program would have to offer all the same run-time dynamic type manipulation and nearly arbitrarily modifiable object instances involved. Not really, it should just offer the same functionality.
- mlthoughts2018 8y agoThat’s exactly my point. When you ask for a native list in Python, you are specifically writing a program that has the functionality of using a list of possibly any type of object. You’re asking for that heterogeneous type flexibility, either because you need it or the overhead doesn’t matter in your case. But either way, by writing that Python program you are saying, “I’d like all this stuff Python gives me.” If you want to write a totally different program, say using a contiguous memory array of a homogeneous type, then you write something different, like with the array.array class, or numpy, or wrap your own thing in Cython. That is the thing whose functionality you’d compare to C/C++, because the functionality goals would be similar. But writing an algorithm that expects tight contiguous memory array operations (or bare metal structs, etc.) in pure Python, it would just be a strawman that is not meaningfully comparable to similar C++ code.
- coldtea 8y ago>That’s exactly my point I don't think so, since I meant "the same functionality as the user visible functionality" -- not that of the language. >You’re asking for that heterogeneous type flexibility, either because you need it or the overhead doesn’t matter in your case. But either way, by writing that Python program you are saying, “I’d like all this stuff Python gives me.” That's irrelevant to the end user though. You could argue that Python makes it faster to deliver the program (which is a win for the end user), but if the program is ultimately slower and more frustrating, the user might have preferred a faster version, if he was given the chance, even if that meant paying more or waiting more to get it.