【问题标题】:Slow performance using scipy.interpolate inside loop在循环内使用 scipy.interpolate 性能下降
【发布时间】:2020-06-18 09:18:14
【问题描述】:

我正在使用 Python 为工程模拟生成输入数据。我需要定义某个物理量(我们称之为力)如何随时间变化。

力取决于一个已知的随时间变化的量(我们称之为角度)。对于每个时间步,力和角度之间的依赖关系是不同的。每个时间步的力角依赖性被定义为数据点,而不是函数。对于每个时间步,我需要从该时间步的力角依赖性中插入力的值。我在列表理解中使用scipy.interpolate.interp1d

但是,我对表现不满意。插值循环需要将近 20 秒,速度慢得让人无法接受。时间步数约为 250k。力角相关性中的数据点数约为 2k。我尝试改用for 循环,但这更慢。

如何提高性能?如果可能,执行时间需要少于一秒。这里的代码不包含我使用的实际数据,但足够相似。

import numpy as np
import random
from scipy.interpolate import interp1d
import time

nTimeSteps = 250000
nPoints_forceAngleDependency = 2000

# Generating an example (bogus data)
angle = np.linspace(0., 2*np.pi, nPoints_forceAngleDependency)
forceAngleDependency_forEachTimeStep = [random.random() * np.sin(angle) for i in range(nTimeSteps)]
angleHistory = [random.random() * 2 * np.pi for i in range(nTimeSteps)]

# Interpolation
start = time.time()
forceHistory = [interp1d(angle, forceAngleDependency_forEachTimeStep[i])(angleHistory[i]) \
    for i in range(nTimeSteps)]
end = time.time()
print 'interpolation duration: %s s' % (end - start)

【问题讨论】:

  • 在不到 1 秒的时间内有 250k 个时间步长,这意味着每个时间步长应该持续不到 4e-6 秒,这对于顺序解释的 Python 代码来说是相当小的。关于点数,也意味着2ns/点的计算速度。此外,这里很难使用并行性,因为必须执行慢速(内核间或进程间)通信(可能在每个时间步)。

标签: python performance scipy scientific-computing


【解决方案1】:
  1. 使用np.random.random(size=nTineSteps)生成样本

  2. 对于线性插值,使用numpy.interp 而不是interp1d。对于高阶样条插值,请使用 CubicSpline 或 make_interp_spline,并使用矢量化评估。

【讨论】:

  • 使用numpy.interp,插值循环的执行时间约为 0.5 秒。使用scipy.interpolate.interp1d 的时间比将近 20 秒有了巨大的改进。谢谢。
猜你喜欢
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
  • 2013-05-17
  • 2019-06-22
  • 2013-09-20
  • 2020-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多