"稀疏" numPy 数组的高效数学运算

2024-09-30 22:09:52 发布

您现在位置:Python中文网/ 问答频道 /正文

在博士论文的模拟中,我面临以下挑战:

我需要优化以下代码:

repelling_forces = repelling_force_prefactor * np.exp(-(height_r_t/potential_steepness))

在这个代码片段中,“height”是一个真正的Numpy数组,“potential”是一个标量排斥“力”prefactor'也是一个Numpy数组,通常为零,但在预先计算的位置有一个,在运行时不会改变(即掩码)。 显然,代码效率低下,因为只计算位置处的指数函数会更有意义,在这些位置,“排斥力”“预因子”为非零。在

问题是我如何以最有效的方式来做这件事?在

到目前为止,我唯一的想法是使用“排斥力”和“应用”将切片定义为“高度”np.exp.公司“对那些切片。然而,我的经验是切片是缓慢的(不确定这是否普遍正确),而且解决方案似乎很尴尬。在

在这个循环中,1的效率很重要。 (评论:我不会有任何问题求助于Cython,因为我需要/想在某个时候学习它。。。但我是个新手,所以我需要一个好的指针/解释。)


Tags: 代码numpynp切片数组potential效率标量
2条回答

切片可能比计算所有的指数要快得多。与其直接使用掩码repelling_force_prefactor进行切片,我建议在索引为非零时预计算索引并将其用于切片:

# before the loop
indices = np.nonzero(repelling_force_prefactor)

# inside the loop
repelling_forces = np.exp(-(height_r_t[indices]/potential_steepness))

现在,repelling_forces将只包含非零的结果。如果必须用此值更新height_r_t的原始形状的某些数组,则可以再次使用indices的切片,或者使用np.put()或类似的函数。在

在这种情况下,使用索引列表进行切片比使用布尔掩码进行切片效率更高,因为索引列表要短1000倍。当然,衡量绩效取决于你自己。在

掩码数组的实现正是为了您的目的。在

表现与斯文的回答相同:

height_r_t = np.ma.masked_where(repelling_force_prefactor == 0, height_r_t)
repelling_forces = np.ma.exp(-(height_r_t/potential_steepness))

遮罩数组的优点是不必对数组进行切片和扩展,其大小始终相同,但numpy自动知道在遮罩数组的情况下不计算exp。在

此外,您可以使用不同的遮罩求和阵列,结果阵列有遮罩的交集。在

相关问题 更多 >