Understanding the differences: A direct comparison between Cython and C++ 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 cython
import 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.a

def 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 None


C++ script:

#include &lt;iostream&gt;
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&lt;N; ++ii)  {
        objArray[ii] = new MathObject(0.2);  // construct new objects
    } // for ii

    for (kk=0; kk&lt;1000; ++kk)  {
    for (jj=0; jj&lt;1000; ++jj)  {
    for (ii=0; ii&lt;N; ++ii)  {
        objArray[ii] -&gt; logMap();
    } // for ii
    } // for jj
    } // for kk

    for (ii=0; ii&lt;N; ++ii)  {
        cout &lt;&lt; objArray[ii] -&gt; a &lt;&lt; "\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.)
Translating python to C++ (just a direct line for line translation).

Headers

import cython                                       #include &lt;iostream&gt;
import numpy as np                                  #include &lt;vector&gt;
                                                    #include "Range.h"
@cython.boundscheck(False)
@cython.wraparound(False)


MathObject

cdef 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;
                                                        }
                                                    };


run

def 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&lt;MathObject&gt; 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&amp; objInstance = objArray[iii];
                objInstance.logMap()                                objInstance.logMap();
                                                                }
                                                            }
        print objArray[i].get_value()                       std::cout &lt;&lt; objArray[i].get_value() &lt;&lt; "\n";
                                                        }

    return None
                                                    }


main

if __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&amp; operator++()     {++value;return *this;}
        int            operator*()      {return value;}
        bool           operator!=(RangeIterator const&amp; 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&amp; operator&lt;&lt;(std::ostream&amp; stream, MathObject const&amp; data)
{
    return stream &lt;&lt; data.a;
}


If values don't change then mark them as const.

int    const one_thousand = 1000;
double const x            = 0.2;