Skip to content

Instantly share code, notes, and snippets.

@bpgergo
Created November 28, 2011 11:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bpgergo/1400141 to your computer and use it in GitHub Desktop.
Save bpgergo/1400141 to your computer and use it in GitHub Desktop.
Concurrent matrix multiplication
import random
import multiprocessing
from itertools import starmap, izip, repeat, imap
from operator import mul
def calc_row_of_product_matrix(a_row, b, izip=izip):
'''Calculate a row of the product matrix P = A * B
Arguments:
a_row is af A
b is the B matrix
returns the corresponding row of P matrix'''
return map(lambda col: sum(starmap(mul,izip(a_row,col))), izip(*b))
def eval_func_tuple(f_args):
'''Takes a tuple of a function and args, evaluates and returns result'''
return f_args[0](*f_args[1:])
class multimatrix(list):
def __mul__(self, b, izip=izip, repeat=repeat):
'''Concurrent matrix multiplication with multiprocessing.Pool. '''
pool = multiprocessing.Pool(multiprocessing.cpu_count())
return pool.map(eval_func_tuple, izip(repeat(calc_row_of_product_matrix), self, repeat(b)))
class itermatrix(list):
@staticmethod
def sumprod(row, col, sum=sum, starmap=starmap, mul=mul):
'''Returns sumproduct of two vectors.'''
return sum(starmap(mul,izip(row,col)))
def __mul__(self, b, imap=imap, izip=izip):
'''Matrix multiplication returning iterable of iterables'''
return imap(lambda row: imap(lambda col: itermatrix.sumprod(row, col), izip(*b)), self)
def iterate_results(result):
'''Iterate over iterable of iterables,
and returns elements in list of lists.
Usage: if you want to run the whole calculation at once:
p = iterate_results(itermatrix([[1, 3], [-5, 6], [2, 4]]) * itermatrix([[1, 4], [8, 7]]))'''
return[[col for col in row] for row in result]
def random_v(K=1000,min=-1000,max=1000):
'''Generates a random vector of dimension N;
Returns a list of integers.
The values are integers in the range [min,max].'''
return [random.randint(min,max) for k in range(K)]
def random_m(N=1000, K=1000):
'''Generates random matrix. Returns list of list of integers.'''
return [random_v(K) for n in range(N)]
from matrix import multimatrix, itermatrix, random_m, iterate_results
import matrix
import timeit
if __name__ == '__main__':
a = [[1, 3], [-5, 6], [2, 4]]
b = [[1, 4], [8, 7]]
adotb = [[25, 25], [43, 22], [34, 36]]
A = multimatrix(a)
B = multimatrix(b)
prod = A * B
assert(adotb == prod)
print prod, "multi test OK"
A = itermatrix(a)
B = itermatrix(b)
iterprod = A * B
listprod = iterate_results(iterprod)
assert(adotb == listprod)
print listprod, "iter test OK"
t = timeit.Timer("p = itermatrix(a) * itermatrix(a)", "from matrix import itermatrix, random_m; a = random_m(500, 500)")
print "iterable product time:", t.timeit(number=1)
t = timeit.Timer("p = itermatrix(a) * itermatrix(a); iterate_results(p)", "from matrix import itermatrix, random_m, iterate_results; a = random_m(500, 500)")
print "list product time:", t.timeit(number=1)
t = timeit.Timer("p = multimatrix(a) * multimatrix(a)", "from matrix import multimatrix, random_m, iterate_results; a = random_m(500, 500)")
print "multi product time:", t.timeit(number=1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment