Python + Numpy: core loop is computationally intensive + benefits from vector ops
Cython: repeated invocations overpower any core loop advantage
In the case of NLP, which is the author's field, you'll find not only do you have an intensive core task, but the number of times you'll call something is insane.
To give an idea: the time complexity for parsing is O(n^3) [n = words in a sentence]. For Combinatory Categorial Grammar (CCG), the formalism that the author Matthew and I commonly use, it's O(n^6). At that point, the inner loop almost doesn't matter -- even if it was just a null op, the function call overheads and everything around it are performance killers. Both of those are what Cython works incredibly well for, especially when you get full control of the data structures.
This is one of those situations where the concept that premature optimization is evil is really quite far off..! =]
I don't see where this is premature optimization. You, and the author, clearly know a lot about the field and the nature of the problem, so you're already past the 'premature' portion. If I know from the start that I've got a function that will be called 10,000 times per second, there's no reason I should write the un-optimized version first. That's like starting every sort off with a bubble sort; I don't need to optimize to quick sort switching off to insertion as appropriate from the beginning of coding, but I know I can do better than bubble from the get-go.
Defining "premature optimization" as the less hyperbolic "optimization before we know we need it," I think it's clear that the problem you've written shows you already know you need it!
Cython: repeated invocations overpower any core loop advantage
In the case of NLP, which is the author's field, you'll find not only do you have an intensive core task, but the number of times you'll call something is insane.
To give an idea: the time complexity for parsing is O(n^3) [n = words in a sentence]. For Combinatory Categorial Grammar (CCG), the formalism that the author Matthew and I commonly use, it's O(n^6). At that point, the inner loop almost doesn't matter -- even if it was just a null op, the function call overheads and everything around it are performance killers. Both of those are what Cython works incredibly well for, especially when you get full control of the data structures.
This is one of those situations where the concept that premature optimization is evil is really quite far off..! =]