我在python中有以下代码:
def P(z, u0):
x = np.inner(z, u0)
tmp = x*u0
return (z - tmp)
def powerA2(A, u0):
x0 = np.random.rand(len(A))
for i in range(ITERATIONS):
x0 = P(np.dot(A, x0), u0)
x0 = x0 / np.linalg.norm(x0)
return (np.inner(np.dot(A, x0), x0))
np
是 numpy
包。
我有兴趣为大小为100,000 * 100,000的矩阵运行此代码,但似乎该程序没有机会快速运行(我需要多次运行,大约10,000次)。
多线程技巧是否有可能在这里发挥作用?
还有什么能帮助加速吗?
答案 0 :(得分:8)
您可以考虑使用Pythran。编译以下代码(norm.py
):
#pythran export powerA2(float [][], float[])
import numpy as np
def P(z, u0):
x = np.inner(z, u0)
tmp = x*u0
return (z - tmp)
def norm(x):
return np.sqrt(np.sum(np.abs(x)**2))
def powerA2(A, u0):
ITERATIONS = 100
x0 = np.random.random(len(A))
for i in range(ITERATIONS):
x0 = P(np.dot(A, x0), u0)
x0 = x0 / norm(x0)
return (np.inner(np.dot(A, x0), x0))
使用:
pythran norm.py
产生以下加速:
$ python -m timeit -s 'import numpy as np; A = np.random.rand(100, 100); B = np.random.random(100); import norm' 'norm.powerA2(A, B)'
100 loops, best of 3: 3.1 msec per loop
$ pythran norm.py -O3 -march=native
$ python -m timeit -s 'import numpy as np; A = np.random.rand(100, 100); B = np.random.random(100); import norm' 'norm.powerA2(A, B)'
1000 loops, best of 3: 937 usec per loop
答案 1 :(得分:2)
只是为了检查:你想做10 ^ 10的10 ^ 4操作......所以即使你的操作是O(1),那仍然是10 ^ 14的操作,这是相当困难的问题(正如haraldkl在他的评论中所指出的那样,这也消耗了大量的内存)只是为了检查:你打算给powerA2召唤10,000次,或者是ITERATIONS所需的10,000。如果是前者,你可以使用线程(或更好的,单独的进程)来获得一些并行化,但我不知道这是否足够;如果是后者,除非我缺少一个技巧,否则你的输入看起来并不平行,因为每个循环迭代的输入都取决于前一个的输出。可能有一种方法可以在GPU上执行此操作(我想认为这是一种至少执行规范化位的有效方法,以便通过使用矢量化可以快速完成大量的操作)
编辑以回应评论:cpython(这是最常见的python实现)具有Global Interpeter Lock(GIL);其他一些python实现(jython,ironpython)没有;每https://wiki.python.org/moin/GlobalInterpreterLock ,.
请注意可能阻塞或长时间运行的操作,例如 I / O,图像处理和NumPy数字运算都发生在外面 GIL。因此,只有在多线程程序中花费很多 GIL内部的时间,解释CPython字节码,即GIL 成为瓶颈。
据我所知,应该可以使用numpy的线程而不是可怕的瓶颈,但你的问题仍然很难转换为线程,除非我缺少一些数学知识。
答案 2 :(得分:2)
通过以这种方式重新定义功能,我比未填充的serge-sans-paille版本提高了10%:
def P0(z, u0):
x = np.inner(z, u0)
x *= u0
return (z - x)
def norm0(x):
return np.sqrt(np.sum(x*x))
def powerA20(A, u0):
ITERATIONS = 100
x0 = np.random.random(len(A))
for i in range(ITERATIONS):
x0 = P0(np.dot(A, x0), u0)
x0 /= norm0(x0)
return (np.inner(np.dot(A, x0), x0))
执行*= u0
而不是x = x*u0
这样的操作可以避免RAM中变量的不必要副本,从而加快程序的运行速度。
此外,在这种情况下,您不需要abs
。最后,x*x
略快于x**2
。