Why is pypy3 slower than python

Viewed 440

In an attempt to run my code faster I thought pypy would be just the job. However, I am finding that it is actually slower for some of my code.

Can someone help me understand why this is the case?

This is the call (a weighted sum) that I have identified which is slower in pypy, which is the main method within a class, at line 663 of functions.py.

It is called 500000 times.

def __call__(self, verbose=False):
    if len(self.links) != self.weights.size:
        raise Exception(f'Number of links ...')

    super().check_links(len(self.links))
    inputs = np.array([link.get_value() for link in self.links])
    self.value = np.dot(inputs, self.weights)

    return super().__call__(verbose)

Here is the snakeviz view of pypy run with cProfile

pypy profile

And here is the snakeviz view run with python

python profile

EDIT: 20210612

@mattip I took your advice and tried a dot product in standard python (sdot). Here are timings with numpy dot (ndot) for python and pypy.

enter image description here

It is good that pypy sdot (0.299) is faster than python sdot (0.749) and faster than both ndots (1.075/4.165). However, what surprises me is that sdot (python lists) is faster than ndot (numpy arrays), with the python interpreter.

Why is that? I had thought that numpy was supposed to be an optimised, fast package for this sort of thing.

Here is the code:

numpy dot product

def runndot(runs):
    weightslist = [0.5, 0.5, 0.5, 0.5, 0.5]
    weights = np.array(weightslist)
    inputslist = [0.1, 0.1, 0.1, 0.1, 0.1]
    inputs = np.array(inputslist)

    for _ in range(runs):
        value = np.dot(inputs, weights)

    return value

python lists dot product

def runsdot(runs):
    weights = [0.5, 0.5, 0.5, 0.5, 0.5]
    inputs = [0.1, 0.1, 0.1, 0.1, 0.1]

    for _ in range(runs):
        value = dot(inputs, weights)
    
    return value

def dot(inputs, weights):
    sum = 0
    for i in range(len(inputs)):
        sum += inputs[i]*weights[i]
    return sum
1 Answers

You are using NumPy, which is written in C. In order for PyPy to use c-extensions like NumPy, it needs to jump through some hoops which make the python-c-python transitions slow. I am not aware of a quick replacement for using np.dot on PyPy, sorry. There is work afoot to make it happen, but it will not be available for a year or two.

You may be interested in using Numba to speed up this kind of code.

If the shape of your array is small, you can hand-write the dot product in python, avoid NumPy, and be fast.

Related