Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
密集矩阵乘法优化在python中效果很小_Python_Optimization_Matrix - Fatal编程技术网

密集矩阵乘法优化在python中效果很小

密集矩阵乘法优化在python中效果很小,python,optimization,matrix,Python,Optimization,Matrix,我想知道为什么I和j上的循环优化反转(应该提供更好的数据局部性)不能与python中的以下代码一起工作: import random import time def fillRand1D(size): return [random.uniform(-2.0, 2.0) for _ in range(size * size)] def mmNaive1D(A, B, size): C = [0] * size * size for i in range(size):

我想知道为什么I和j上的循环优化反转(应该提供更好的数据局部性)不能与python中的以下代码一起工作:

import random
import time

def fillRand1D(size):
    return [random.uniform(-2.0, 2.0) for _ in range(size * size)]

def mmNaive1D(A, B, size):
    C = [0] * size * size
    for i in range(size):
        for j in range(size):
            for k in range(size):
                C[i * size + j] += A[i * size + k] * B[k * size + j]
    return C

def mmInvariant1D(A, B, size):
    C = [0] * size * size
    for i in range(size):
        for j in range(size):
            sigma = C[i * size + j]
            for k in range(size):
                sigma += A[i * size + k] * B[k * size + j]
            C[i * size + j] = sigma
    return C


def mmLoop1D(A, B, size):
    C = [0] * size * size
    for k in range(size):
        for i in range(size):
            for j in range(size):
                C[i * size + j] += A[i * size + k] * B[k * size + j]
    return C


def mmLoopInvariant1D(A, B, size):
    C = [0] * size * size
    for k in range(size):
        for i in range(size):
            Aik = A[i * size + k]
            for j in range(size):
                C[i * size + j] += Aik * B[k * size + j]
    return C

def main():
    matmul_func_1D = [mmNaive1D,mmInvariant1D,mmLoop1D,mmLoopInvariant1D]
    size = 200
    A_1D = fillRand1D(size)
    B_1D = fillRand1D(size)

    for f in matmul_func_1D:
        A = A_1D[:] # copy !
        B = B_1D[:]
        start_time = time.time()
        C = f(A_1D,B_1D,size)
        # print(T)
        print(f.__name__ + " in " + str(time.time() - start_time) + " s")

if __name__ == '__main__':
    main()
python的结果如下:

mmNaive1D in 3.420367956161499 s  
mmInvariant1D in 2.316128730773926 s  
mmLoop1D in 3.4071271419525146 s  
mmLoopInvariant1D in 2.5221548080444336 s
< C++ >相同的优化给出:

> Time [MM naive] 1.780587 s
> Time [MM invariant] 1.642554 s
> Time [MM loop IKJ] 0.304621 s
> Time [MM loop IKJ invariant] 0.276159 s

您的
A、B和C
矩阵是python列表,对于大维度来说速度非常慢。您可以将它们创建为numpy阵列,以尝试加快功能:

>>> import numpy as np
>>> A = np.random.uniform(-2., 2., (size,size))
>>> B = np.random.uniform(-2., 2., (size,size))
这将
A
B
矩阵定义为
size x size
随机矩阵

代码的瓶颈是python循环。Python循环相当慢,您希望尽可能在代数运算中避免它们。在你的例子中,你想要实现的(如果我没有错的话)是
C=A*B
where*是两个2D矩阵之间的点积。翻译成numpy:

>>> C = A.dot(B)
如果你计时:

>>> %timeit C = A.dot(B)
100 loops, best of 3: 7.91 ms per loop
只需
7.91 ms
即可计算点积。我知道你想玩python,但是如果你想做数学演算,你越早去numpy,你的算法的速度就越好

回到您的算法,如果我在我的计算机上运行您的代码,优化确实有效,并实现了一定的加速:

mmNaive1D in 1.72708702087 s
mmInvariant1D in 1.64227509499 s
mmLoop1D in 1.57529997826 s
mmLoopInvariant1D in 1.26218104362 s
所以这对我来说很有效

编辑:在多次运行代码后,我得到了不同的结果:

mmNaive1D in 1.63492894173 s
mmInvariant1D in 1.1577808857 s
mmLoop1D in 1.67409181595 s
mmLoopInvariant1D in 1.32283711433 s
这次“优化”不起作用。我猜这是因为算法的瓶颈是python循环,而不是内存访问

EDIT2:一些更相关的结果执行每个算法的100次迭代以获得平均计时(花了一段时间哈哈):


即使100次迭代仍然不够相关(比如1.000.000次会更好,但需要花费很多时间),这表明作为100次运行时的平均值,“优化”并不是真正的优化。我真的不知道为什么,但可能是在python中添加一个新变量要比200次内存访问慢(可能后面有一些缓存)。

python列表不是连续数组,因此优化在这里没有什么作用,我很抱歉。哦,谢谢,如果我使用的是连续的数组,我想它可能会工作。如果你需要能够指定连续性,Numpy是优化这类过程的好地方。。。当然,您可以只使用numpy.multiplyYes,但是对于python
for
循环进行的所有类型检查,您可能看不到数据局部性的优势。正如en_Knight所说,对于任何真正的数组计算,您最好使用
numpy
,尽管我怀疑您只是在玩弄一些东西。确切地说,我只是想玩一下Python,我会尝试使用numpy,谢谢!谢谢伊伦戈的回答。事实上,我的问题是为什么数据局部性优化不起作用。正如我在评论中所说,我尝试将连续数组与numpy.ascontiguousarray一起使用,但没有成功。我想你是对的,瓶颈不是内存访问。我只是用每个函数100次迭代的平均时间进行了编辑。希望你感到好奇:P
mmNaive1D in 1.66692941904 s
mmInvariant1D in 1.15141540051 s
mmLoop1D in 1.58852998018 s
mmLoopInvariant1D in 1.28386260986 s