我在想是否有可能使用Numpy
或数学技巧来优化以下内容。
def f1(g, b, dt, t1, t2):
p = np.copy(g)
for i in range(dt):
p += t1*np.tanh(np.dot(p, b)) + t2*p
return p
其中g
是长度为n
的向量,b
是一个 n
xn
的矩阵,dt
是迭代次数,t1
和t2
是标量。
我已经很快地想不出如何进一步优化这个函数了,因为在循环中,在方程的所有三个项中都使用了p
:当加到自身时;在点积中;在标量乘法中。
但也许有一种不同的方式来表示这个函数或者有其他的技巧来提高它的效率。如果可能的话,我更倾向于不使用Cython
等工具,但如果速度提升显著,我愿意使用它。预先感谢你们的帮助,如果这个问题在某些方面超出范围,请原谅。
更新:
到目前为止提供的答案更加关注输入/输出值的取值,以避免不必要的操作。我现在已经更新了MWE,为变量提供了适当的初始化值(我没有期望优化的想法来自那边 - 抱歉)。g
将在范围[-1, 1]
内,b
将在范围[-无穷大,无穷大]
内。近似输出不是一个选择,因为返回的向量稍微相似的输入可能会得到相同的向量,因此这不是一个选择。
MWE:
import numpy as np
import timeit
iterations = 10000
setup = """
import numpy as np
n = 100
g = np.random.uniform(-1, 1, (n,)) # Updated.
b = np.random.uniform(-1, 1, (n,n)) # Updated.
dt = 10
t1 = 1
t2 = 1/2
def f1(g, b, dt, t1, t2):
p = np.copy(g)
for i in range(dt):
p += t1*np.tanh(np.dot(p, b)) + t2*p
return p
"""
functions = [
"""
p = f1(g, b, dt, t1, t2)
"""
]
if __name__ == '__main__':
for function in functions:
print(function)
print('Time = {}'.format(timeit.timeit(function, setup=setup,
number=iterations)))
numba.jit
(http://numba.pydata.org/)应该适用的类型(Cython也是如此)。 然而,这是一个重要的依赖项,如果可能的话,您确实表示更愿意坚持使用“纯粹”的numpy。 - Joe KingtonCython
,但速度提升微不足道。我想这是因为 (a) 我对Cython
不熟悉; (b) 我保持了大部分相同的东西,而没有例如在点积中使用C
循环。如果Cython
可以显著提高性能,我会非常高兴切换到它。现在看看numba.jit
-- 谢谢!:-)
- sudosenseiDGEMM
调用的效率将对整体速度产生最大的贡献。您当前正在使用优化的BLAS与NumPy吗?当然,这是在您使用比您描述的更大的矩阵的情况下,因为每次调用仅需要250微秒。 - DanielCython
运行我的测试时,我进行了1000多次迭代,但是我没有看到任何显著的改进 - 但是,我将这归因于我对Cython
知识的不足,而不是潜力的不足。另外,是的,我正在使用优化的BLAS与Numpy
。迭代次数和矩阵长度通常都会小于1000,但是这个函数被调用的次数超过一百万次。即使仅仅减少10%的执行时间,也将是一个显著的改进。 - sudosensei