Search code examples
pythonnumpyperformanceperfplot

Perfplot to compare performance of several functions with multiple arguments (more than one)


I would like to show performance of some functions by perfplot that uses more than one arguments, but I don't know how could I do this (I'm not familiar much with perfplot). One said broadcast all args to just x, but I am confused yet how to use it. Assume we have the following functions:

from scipy.ndimage import zoom
import numpy as np

f = 5
n = 3
arr = np.random.random_integers(0, 1, (f, f))

def scipy_zoom(arr, n):
    return zoom(arr, n)

def numpy_rep(arr, n):
    return arr.repeat(n, 0).repeat(n, 1)

Both f and n changes need to be evaluated and it seems it will be better to plot them separately i.e. once f be constant and n varies and once vice-versa. I don't know how understandable it will be if the 3D perfplot could be plotted (this will be useful if be shown in the answers, but not the main aim of this question).


Solution

  • For two arguments we can collect all benchmark timings, setting the range of f for arr size with functools.partial and the range of n within perfplot

    import perfplot
    from functools import partial
    
    res = []
    for f in range(5,100,20):
        arr = np.random.randint(0, 2, (f, f))
        g = perfplot.bench(
            setup=lambda n: n,
            kernels=[partial(scipy_zoom, arr),
                     partial(numpy_rep, arr)],
            labels=['zoom','numpy'],
            n_range=[2,3,4,5,6,7,8,9,10],
            equality_check=False # results are not equal!
        )
        res.append(g)
    

    and plot a 3D graph of 2D line plot layers.

    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    from cycler import cycler
    
    
    fig = plt.figure(figsize=(10,8))
    ax = fig.add_subplot(111, projection='3d')
    cc = cycler(color=list('rg'))
    
    for i, g in zip(range(5,100,20)[::-1],res[::-1]):  # plot from back to front
        ax.plot(g.n_range,g.timings_s.T, i, zdir='y', alpha=0.8)
    
    plt.rc('axes', prop_cycle=cc)
    ax.set_xlabel('n')
    ax.set_ylabel('f')
    ax.set_zlabel('seconds')
    ax.legend(g.labels)
    plt.show()
    

    Output

    results