Skip to main content

Fast repeated multiplication of 2x2 matrices in a compiled numpy extension

Project description

MatProd

Fast repeated multiplication of 2x2 matrices in a compiled numpy extension.

Why does this exist

This extension is the solution to a performance problem with the repeated multiplication of 2x2 numpy matrices in python. For some applications in computational science, it is necessary to take the product of between 1E4 and 1E8 matrices in a performant manner. In numpy this can be done with a for loop. However, this introduces a tight loop in python which adds significant overhead to the task. In addition, if the matrices being multiplied are small, there is additional overhead in the for loops used for the matrix product that may be avoided. The performance difference between the python implementation and this c implementation of repeated matrix multiplication is order of magnitude 1,000x.

Installation

This package is available through on PyPi. Simply run pip install matprod.

Usage

All functions in the library accept a numpy array of the n 2x2 matrices to be multiplied together. The array Ms should have the shape (2,2,n) where Ms[:,:,0] is the first matrix, Ms[:,:,1] is the second, and so on.

Two functions are presently exported from the extension. These are lprod(Ms) and cumlprod(Ms) which perform the repeated matrix left product and the cumulative left product of the matrices respectively. By left product I mean that the result of lprod(Ms) is equivalent to the code Ms[:,:,n] @ ... @ Ms[:,:,2] @ Ms[:,:,1] @ Ms[:,:,0] in numpy. The cumulative left product will also return all of the intermediate products in a (2,2,n) numpy array. The first element will be ret[:,:,0] = Ms[:,:,0], the second and third will be ret[:,:,0] = Ms[:,:,1] @ Ms[:,:,0], ret[:,:,0] = Ms[:,:,2] @ Ms[:,:,1] @ Ms[:,:,0], and so on.

Test the code out with this simple example:

import matprod

# Create a set of matrices to multiply
Ms = np.random.rand(2,2,10000)

# Take the left product
print(matprod.lprod(Ms))

# Try out the cumulative product
print(matprod.cumlprod(Ms)[:,:,-1])

Performance

The time taken to multiply 10,000 2x2 matrices by a python implementation and this library can be compared with the following scripts.

import matprod
import numpy as np
import timeit
import functools as f

# Make a test array
arr = np.random.rand(2,2,10000)*1.06

# Test the speed of the new method
testfun_new = lambda: matprod.lprod(arr)
print("Execution Time New: {:.0f} us".format(timeit.timeit(testfun_new, number=10000)/10000*1e6))

# Test the speed of the old method
testfun_old = lambda: f.reduce(np.dot, arr.T).T
print("Execution Time Old: {:.0f} ms".format(timeit.timeit(testfun_old, number=100)/100*1e3))

# Make sure they are the same
print()
print('Relative Difference of Elements:')
print((testfun_new() - testfun_old())/testfun_old())

On my 2016-era laptop, the output of this scripts was

Execution Time New: 37 us
Execution Time Old: 25 ms

Relative Difference of Elements:
[[-6.56716376e-16 -1.34748247e-15]
 [-9.04050404e-16 -1.27529490e-15]]

This is a nearly three orders of magnitude speed-up over the python implementation! The results are also identical to machine precision.

Reporting Issues and Feature Requests

Please file an issue on the projects github page here.

Project details


Release history Release notifications | RSS feed

This version

1.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matprod-1.0.tar.gz (4.8 kB view hashes)

Uploaded Source

Built Distributions

matprod-1.0-pp37-pypy37_pp73-win32.whl (21.3 kB view hashes)

Uploaded PyPy Windows x86

matprod-1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (18.2 kB view hashes)

Uploaded PyPy macOS 10.9+ x86-64

matprod-1.0-pp36-pypy36_pp73-win32.whl (21.2 kB view hashes)

Uploaded PyPy Windows x86

matprod-1.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl (19.7 kB view hashes)

Uploaded PyPy manylinux: glibc 2.12+ x86-64

matprod-1.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl (18.2 kB view hashes)

Uploaded PyPy macOS 10.9+ x86-64

matprod-1.0-pp36-pypy36_pp73-macosx_10_7_x86_64.whl (18.2 kB view hashes)

Uploaded PyPy macOS 10.7+ x86-64

matprod-1.0-cp39-cp39-win_amd64.whl (23.4 kB view hashes)

Uploaded CPython 3.9 Windows x86-64

matprod-1.0-cp39-cp39-win32.whl (21.2 kB view hashes)

Uploaded CPython 3.9 Windows x86

matprod-1.0-cp39-cp39-macosx_10_9_x86_64.whl (18.4 kB view hashes)

Uploaded CPython 3.9 macOS 10.9+ x86-64

matprod-1.0-cp38-cp38-win_amd64.whl (23.4 kB view hashes)

Uploaded CPython 3.8 Windows x86-64

matprod-1.0-cp38-cp38-win32.whl (21.2 kB view hashes)

Uploaded CPython 3.8 Windows x86

matprod-1.0-cp38-cp38-manylinux2010_x86_64.whl (35.0 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

matprod-1.0-cp38-cp38-manylinux2010_i686.whl (33.1 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ i686

matprod-1.0-cp38-cp38-manylinux1_x86_64.whl (35.0 kB view hashes)

Uploaded CPython 3.8

matprod-1.0-cp38-cp38-manylinux1_i686.whl (33.1 kB view hashes)

Uploaded CPython 3.8

matprod-1.0-cp38-cp38-macosx_10_9_x86_64.whl (18.4 kB view hashes)

Uploaded CPython 3.8 macOS 10.9+ x86-64

matprod-1.0-cp37-cp37m-win_amd64.whl (27.6 kB view hashes)

Uploaded CPython 3.7m Windows x86-64

matprod-1.0-cp37-cp37m-win32.whl (21.1 kB view hashes)

Uploaded CPython 3.7m Windows x86

matprod-1.0-cp37-cp37m-manylinux2010_x86_64.whl (35.8 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

matprod-1.0-cp37-cp37m-manylinux2010_i686.whl (33.9 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.12+ i686

matprod-1.0-cp37-cp37m-manylinux1_x86_64.whl (35.8 kB view hashes)

Uploaded CPython 3.7m

matprod-1.0-cp37-cp37m-manylinux1_i686.whl (33.9 kB view hashes)

Uploaded CPython 3.7m

matprod-1.0-cp37-cp37m-macosx_10_9_x86_64.whl (18.3 kB view hashes)

Uploaded CPython 3.7m macOS 10.9+ x86-64

matprod-1.0-cp36-cp36m-win_amd64.whl (23.3 kB view hashes)

Uploaded CPython 3.6m Windows x86-64

matprod-1.0-cp36-cp36m-win32.whl (21.1 kB view hashes)

Uploaded CPython 3.6m Windows x86

matprod-1.0-cp36-cp36m-manylinux2010_x86_64.whl (34.8 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.12+ x86-64

matprod-1.0-cp36-cp36m-manylinux2010_i686.whl (33.0 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.12+ i686

matprod-1.0-cp36-cp36m-manylinux1_x86_64.whl (34.8 kB view hashes)

Uploaded CPython 3.6m

matprod-1.0-cp36-cp36m-manylinux1_i686.whl (33.0 kB view hashes)

Uploaded CPython 3.6m

matprod-1.0-cp36-cp36m-macosx_10_9_x86_64.whl (18.3 kB view hashes)

Uploaded CPython 3.6m macOS 10.9+ x86-64

matprod-1.0-cp35-cp35m-win_amd64.whl (23.3 kB view hashes)

Uploaded CPython 3.5m Windows x86-64

matprod-1.0-cp35-cp35m-win32.whl (21.1 kB view hashes)

Uploaded CPython 3.5m Windows x86

matprod-1.0-cp35-cp35m-manylinux2010_x86_64.whl (34.6 kB view hashes)

Uploaded CPython 3.5m manylinux: glibc 2.12+ x86-64

matprod-1.0-cp35-cp35m-manylinux2010_i686.whl (32.7 kB view hashes)

Uploaded CPython 3.5m manylinux: glibc 2.12+ i686

matprod-1.0-cp35-cp35m-manylinux1_x86_64.whl (34.6 kB view hashes)

Uploaded CPython 3.5m

matprod-1.0-cp35-cp35m-manylinux1_i686.whl (32.7 kB view hashes)

Uploaded CPython 3.5m

matprod-1.0-cp35-cp35m-macosx_10_9_x86_64.whl (18.3 kB view hashes)

Uploaded CPython 3.5m macOS 10.9+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page