Introduction:The following two code samples are a direct comparison of performance between Cython and C++. I pieced them together with the help of others-- I barely understand how they work. Their speed in my computer is: 1.225s vs 3.989s (C++ being the faster). The purpose of this comparison is to decide which language I will be using for a series of small but computationally intensive scripts (~200-500 lines).Question:As a novice Python programmer dealing with data types, memory (de)allocation, and other low level processes for the very first time, what should I keep in mind when writing Cython modules? Is there anything in the Cython code that can be improved?Cython script:import cythonimport numpy as np@cython.boundscheck(False)@cython.wraparound(False)cdef class MathObject:    cdef double a    def __init__(self, a):        self.a = a    # chaotic function (simple math that can't be simplified out by the compiler).    cpdef double logMap(self):        self.a = 4.0 * self.a * (1.0 - self.a)        return 0    def get_value(self):        return self.adef run():    cdef int i, ii, iii    cdef int one_thousand = 1000    cdef double x = 0.2  # logMap has complex behavior at this value    cdef MathObject objInstance    objArray = np.empty(one_thousand, dtype=MathObject)    for i in range(len(objArray)):        objArray[i] = MathObject(x)    cdef MathObject[:] objArrayiew = objArray    for i in range(one_thousand):        for ii in range(one_thousand):            for iii in range(one_thousand):                objInstance = objArrayiew[iii]                objInstance.logMap()        print objArray[i].get_value()    return NoneC++ script:#include <iostream>using namespace std;class MathObject {    public:    double a;    MathObject(double b) {        a=b;    };    // simple chaotic function    double logMap()    {        a = 4.0*a*(1.0-a);    } // logMap};int main(int argc, char *argv[]){    int ii,jj,kk;    // create an array of 1000 objects    int N = 1000;    MathObject *objArray [N];  // 1000 pointers to objects    for (ii=0; ii<N; ++ii)  {        objArray[ii] = new MathObject(0.2);  // construct new objects    } // for ii    for (kk=0; kk<1000; ++kk)  {    for (jj=0; jj<1000; ++jj)  {    for (ii=0; ii<N; ++ii)  {        objArray[ii] -> logMap();    } // for ii    } // for jj    } // for kk    for (ii=0; ii<N; ++ii)  {        cout << objArray[ii] -> a << \n;    } // for ii}(Note: I know that this question is a little vague, but most existing tutorials for Cython are written for an audience of C++ programmers. Beginner level information is astoundingly helpful!)(Second Note: A good explanation of part of the Cython script can be found in the answer to this question.)
Understanding the differences: A direct comparison between Cython and C++
python;c++;performance;comparative review;cython
Translating python to C++ (just a direct line for line translation).Headersimport cython                                       #include <iostream>import numpy as np                                  #include <vector>                                                    #include Range.h@cython.boundscheck(False)@cython.wraparound(False)MathObjectcdef class MathObject:                              struct MathObject {    cdef double a                                       double a;    def __init__(self, a):                              MathObject(double a)        self.a = a                                          : a(a)                                                        {}    cpdef double logMap(self):                          double logMap() {        self.a = 4.0 * self.a * (1.0 - self.a)              a = 4.0 * a * (1.0 - a);        return 0                                            return 0;                                                        }    def get_value(self):                                double get_value() {        return self.a                                       return a;                                                        }                                                    };rundef run():                                          void run() {    cdef int i, ii, iii    cdef int one_thousand = 1000                        int one_thousand = 1000;    cdef double x = 0.2                                 double x = 0.2;    cdef MathObject objInstance    objArray = np.empty(one_thousand, dtype=MathObject) std::vector<MathObject> objArray(one_thousand, x);    for i in range(len(objArray)):        objArray[i] = MathObject(x)    cdef MathObject[:] objArrayiew = objArray    for i in range(one_thousand):                       for(int i: Range(one_thousand)) {        for ii in range(one_thousand):                      for(int ii: Range(one_thousand)) {            for iii in range(one_thousand):                     for(int iii: Range(one_thousand)) {                objInstance = objArrayiew[iii]                      MathObject& objInstance = objArray[iii];                objInstance.logMap()                                objInstance.logMap();                                                                }                                                            }        print objArray[i].get_value()                       std::cout << objArray[i].get_value() << \n;                                                        }    return None                                                    }mainif __name__ == __main__:                          int main() {    run()                                               run();                                                    }In C++ there is no built in Range type. But it is easy to write:class Range{    int beginValue;    int endValue;    struct RangeIterator    {        int value;        RangeIterator(int v) : value(v) {}        RangeIterator& operator++()     {++value;return *this;}        int            operator*()      {return value;}        bool           operator!=(RangeIterator const& rhs) const {return value != rhs.value;}    };    public:        typedef RangeIterator           iterator;        Range(int e)            : Range(0, e)        {}        Range(int b, int e)            : beginValue(b), endValue(e)        {}        iterator begin() { return RangeIterator(beginValue);}        iterator end()   { return RangeIterator(endValue);}};A couple of notes on the direct translation that I would change:If you are not going to return a meaningful value (and we notice from usage that the return value is ignored).double logMap() {    a = 4.0 * a * (1.0 - a);    return 0;}Then I would make this a void function so you know its not supposed to return anything.void logMap() {    a = 4.0 * a * (1.0 - a);}I don't like geters they break encapsulation:double get_value() {    return a;}You usually find that if you are getting values from an object doing stuff with it there is usally a member function (or member of the public API) that can do that. In this case you are only using the value to print. So why not just create a function that knows how to print the value.friend std::ostream& operator<<(std::ostream& stream, MathObject const& data){    return stream << data.a;}If values don't change then mark them as const.int    const one_thousand = 1000;double const x            = 0.2;