Skip to main content
 首页 » 编程设计

Python并行矩阵向量乘法

2025年05月04日14mfryf

我正在尝试将矩阵的每一列乘以向量元素。

我有一个可以正常工作的串行解决方案。

    for i in range(0,temp.shape[0]): 
        for j in range(0,temp.shape[1]): 
             temp[i,j] = temp[i,j] * h[i,0] 

下面是适用于我正在尝试做的事情的并行解决方案,但不会返回与上述代码相同的矩阵。

def mv_mult(start_col,end_col,M,V): 
for i in range(0,M.shape[0]): 
    for j in range(start_col,end_col): 
        M[i,j] = M[i,j] * V[i,0] 
 
num_threads = multiprocessing.cpu_count() 
threads = [] 
extra = temp.shape[1] % num_threads 
start_col = 0 
jump = temp.shape[1] / num_threads 
for i in range(0,num_threads): 
    print 'starting thread ', i 
    if (i <  extra) 
        args = start_col, start_col+jump+1,temp,h 
        p = multiprocessing.Process(target=mv_mult,args=args) 
        p.start() 
        threads.append(p) 
        start_col += jump+1 
    else: 
        args = start_col, start_col+jump,temp,h 
        p = multiprocessing.Process(target=mv_mult,args=args) 
        p.start() 
        threads.append(p) 
        start_col += jump 
 
for i in threads: 
    i.join() 

我对 Python 比较陌生,但据我所知,一切都是通过引用传递的,因此传递给每个新进程的临时矩阵是同一个对象,所以它应该与串行解决方案一样工作,减去事实它按列拆分。

关于为什么它不起作用的任何想法?

请您参考如下方法:

这只是 numpy 的 multiply 操作:

import numpy 
 
a = numpy.matrix(numpy.ones((5,5))) 
b = numpy.arange(5).reshape(5,1) 
print a 
print b     
#[[ 1.  1.  1.  1.  1.] 
# [ 1.  1.  1.  1.  1.] 
# [ 1.  1.  1.  1.  1.] 
# [ 1.  1.  1.  1.  1.] 
# [ 1.  1.  1.  1.  1.]] 
#[[0] 
# [1] 
# [2] 
# [3] 
# [4]] 
 
c = numpy.multiply(a,b) 
print c 
#[[ 0.  0.  0.  0.  0.] 
# [ 1.  1.  1.  1.  1.] 
# [ 2.  2.  2.  2.  2.] 
# [ 3.  3.  3.  3.  3.] 
# [ 4.  4.  4.  4.  4.]] 

(请注意,在您的串行版本中,您乘以行,而不是列)。

将此时间与您的串行版本进行比较:

#!/usr/bin/env python 
 
import numpy 
import numpy.random 
import numpy.linalg 
import sys 
import time 
 
def init(n): 
    a = numpy.matrix(numpy.random.rand(n,n)) 
    b = numpy.random.rand(n,1) 
    b = b.reshape((n,1)) 
    return a,b 
 
def np_mult(a, b): 
    c = numpy.multiply(a,b) 
    return c 
 
def manual_mult(a,b): 
    c = numpy.matrix(numpy.zeros_like(a)) 
    for i in range(0,a.shape[0]): 
        for j in range(0,a.shape[1]): 
             c[i,j] = a[i,j] * b[i] 
    return c 
 
def main(argv=None): 
    if argv is None: 
        argv = sys.argv 
 
    n = int(argv[1]) 
    niters = int(argv[2]) 
    a,b = init(n) 
 
    start = time.time() 
    for i in xrange(niters): 
        cnp = np_mult(a,b) 
    end = time.time() 
 
    nptime = (end-start)/niters 
    print 'Numpy: ', nptime 
 
    start = time.time() 
    for i in xrange(niters): 
        cm = manual_mult(a,b) 
    end = time.time() 
 
    manualtime = (end-start)/niters 
    print 'Manual: ', manualtime 
    print 'Speed difference = ', manualtime/nptime 
    print 'Diff = ', numpy.linalg.norm(cm - cnp)/numpy.linalg.norm(cnp) 
 
    return 0 
 
if __name__ == "__main__": 
    sys.exit(main()) 

运行一些小尺寸会得到:

$ ./mult.py 50 5 
Numpy:  3.48091125488e-05 
mManual:  0.021101808548 
Speed difference =  606.215068493 
Diff =  0.0 
 
$ ./mult.py 100 5 
Numpy:  6.59942626953e-05 
Manual:  0.0830503940582 
Speed difference =  1258.44869942 
Diff =  0.0 
 
$ ./mult.py 500 5 
Numpy:  0.000931406021118 
Manual:  2.08903641701 
Speed difference =  2242.88481032 
Diff =  0.0 

速度差异使您可以通过并行性弥补的任何事情都相形见绌。