def python_bubblesort(a_list): """ Bubblesort in Python for list objects. """ length = len(a_list) swapped = 1 for i in xrange(0, length): if swapped: swapped = 0 for ele in xrange(0, length-i-1): if a_list[ele] > a_list[ele + 1]: temp = a_list[ele + 1] a_list[ele + 1] = a_list[ele] a_list[ele] = temp swapped = 1 return a_list def python_bubblesort_ary(np_ary): """ Bubblesort in Python for NumPy arrays. """ length = np_ary.shape[0] swapped = 1 for i in xrange(0, length): if swapped: swapped = 0 for ele in xrange(0, length-i-1): if np_ary[ele] > np_ary[ele + 1]: temp = np_ary[ele + 1] np_ary[ele + 1] = np_ary[ele] np_ary[ele] = temp swapped = 1 return np_ary %load_ext cythonmagic %%cython import numpy as np cimport numpy as np cimport cython @cython.boundscheck(False) @cython.wraparound(False) cpdef cython_bubblesort(inp_ary): """ The Cython implementation of Bubblesort with NumPy memoryview.""" cdef unsigned long length, i, swapped, ele, temp cdef long[:] np_ary = inp_ary length = np_ary.shape[0] swapped = 1 for i in xrange(0, length): if swapped: swapped = 0 for ele in xrange(0, length-i-1): if np_ary[ele] > np_ary[ele + 1]: temp = np_ary[ele + 1] np_ary[ele + 1] = np_ary[ele] np_ary[ele] = temp swapped = 1 return inp_ary from numba import jit as numba_jit @numba_jit def numba_bubblesort(np_ary): """ The NumPy implementation of Bubblesort on NumPy arrays.""" length = np_ary.shape[0] swapped = 1 for i in xrange(0, length): if swapped: swapped = 0 for ele in xrange(0, length-i-1): if np_ary[ele] > np_ary[ele + 1]: temp = np_ary[ele + 1] np_ary[ele + 1] = np_ary[ele] np_ary[ele] = temp swapped = 1 return np_ary from parakeet import jit as para_jit @para_jit def parakeet_bubblesort(np_ary): """ The parakeet implementation of Bubblesort on NumPy arrays.""" length = np_ary.shape[0] swapped = 1 for i in xrange(0, length): if swapped: swapped = 0 for ele in xrange(0, length-i-1): if np_ary[ele] > np_ary[ele + 1]: temp = np_ary[ele + 1] np_ary[ele + 1] = np_ary[ele] np_ary[ele] = temp swapped = 1 return np_ary import random import copy import numpy as np random.seed(4354353) l = np.asarray([random.randint(1,1000) for num in xrange(1, 1000)]) l_sorted = np.sort(l) for f in [python_bubblesort, python_bubblesort_ary, cython_bubblesort, numba_bubblesort, parakeet_bubblesort]: assert(l_sorted.all() == f(copy.copy(l)).all()) print('Bubblesort works correctly') import timeit import copy import numpy as np funcs = ['python_bubblesort', 'python_bubblesort_ary', 'cython_bubblesort', 'numba_bubblesort', 'parakeet_bubblesort' ] orders_n = [10**n for n in range(1, 6)] timings = {f:[] for f in funcs} for n in orders_n: l = [np.random.randint(n) for num in range(n)] for f in funcs: l_copy = copy.deepcopy(l) if f != 'python_bubblesort': l_copy = np.asarray(l_copy) timings[f].append(min(timeit.Timer('%s(l_copy)' %f, 'from __main__ import %s, l_copy' %f) .repeat(repeat=3, number=10))) import platform import multiprocessing from cython import __version__ as cython__version__ from llvm import __version__ as llvm__version__ from numba import __version__ as numba__version__ from parakeet import __version__ as parakeet__version__ def print_sysinfo(): print '\nPython version :', platform.python_version() print 'compiler :', platform.python_compiler() print 'Cython version :', cython__version__ print 'NumPy version :', np.__version__ print 'Numba version :', numba__version__ print 'llvm version :', llvm__version__ print 'parakeet version:', parakeet__version__ print '\nsystem :', platform.system() print 'release :', platform.release() print 'machine :', platform.machine() print 'processor :', platform.processor() print 'CPU count :', multiprocessing.cpu_count() print 'interpreter:', platform.architecture()[0] print '\n\n' %matplotlib inline import matplotlib.pyplot as plt def plot(timings, title, ranked_labels, labels, orders_n): plt.rcParams.update({'font.size': 12}) fig = plt.figure(figsize=(11,10)) for lb in ranked_labels: plt.plot(orders_n, timings[lb], alpha=0.5, label=labels[lb], marker='o', lw=3) plt.xlabel('sample size n (items in the list)') plt.ylabel('time per computation in milliseconds') plt.xlim([min(orders_n) / 10, max(orders_n)* 10]) plt.legend(loc=2) plt.grid() plt.xscale('log') plt.yscale('log') plt.title(title) plt.show() import prettytable def summary_table(ranked_labels): fit_table = prettytable.PrettyTable(['n=%s' %orders_n[-1], 'bubblesort function' , 'time in millisec.', 'rel. performance gain']) fit_table.align['bubblesort function'] = 'l' for entry in ranked_labels: fit_table.add_row(['', labels[entry[1]], round(entry[0]*100, 3), round(ranked_labels[0][0]/entry[0], 2)]) # times 100 for converting from seconds to milliseconds: (time*1000 / 10-loops) print(fit_table) title = 'Performance of Bubblesort in Python, Cython, parakeet, and Numba' labels = {'python_bubblesort':'(C)Python Bubblesort - Python lists', 'python_bubblesort_ary':'(C)Python Bubblesort - NumPy arrays', 'cython_bubblesort': 'Cython Bubblesort - NumPy arrays', 'numba_bubblesort': 'Numba Bubblesort - NumPy arrays', 'parakeet_bubblesort': 'parakeet Bubblesort - NumPy arrays' } ranked_by_time = sorted([(time[1][-1],time[0]) for time in timings.items()], reverse=True) print_sysinfo() plot(timings, title, [l for t,l in ranked_by_time], labels, orders_n) summary_table(ranked_by_time)