我正在重写Molecular Dynamics时间序列的分析代码。由于需要分析大量的时间步长(每次模拟运行150 000次),因此我的代码尽可能快地非常重要。
旧代码非常慢(实际上它需要比我的时间多300到500倍),因为它是为分析几千个PDB文件编写的,而不是一堆完整的不同模拟(大约60个),每个人有150 000个时间步。我知道在这种情况下C或Fortran将成为瑞士军刀,但我对c的经验是......
因此,我试图尽可能多地使用我的python代码的numpy / scipy例程。因为我已经获得了使用mkl加速分发anaconda的许可证,这是一个非常重要的加速。
现在我遇到了一个问题,我希望我能以你明白我的意思解释它。
我有三个阵列,每个阵列的形状为(n,3,20)。在第一行是我的肽的所有残差,通常在23到31左右。在第二行是xyz和第三行的坐标是一些特定的时间步。
现在我计算每个时间步的每个残差的扭转。我的代码用于形状为(n,3,1)的数组:
def fast_torsion(d1, d2, d3):
tt = dot(d1, np.cross(d2, d3))
tb = dot(d1, d1) * dot(d2, d2)
torsion = np.zeros([len(d1), 1])
for i in xrange(len(d1)):
if tb[i] != 0:
torsion[i] = tt[i]/tb[i]
return torsion
现在我尝试对具有扩展第三轴的数组使用相同的代码,但是与使用for循环的原始慢速代码相比,交叉乘积函数产生错误的值。 我用我的大数组尝试了这个代码,它比for循环解决方案快了大约10到20倍,比旧代码快了大约200倍。
我正在尝试的是np.cross()仅计算第二个(xyz)轴上的叉积并迭代另外两个轴。在短第三轴的情况下,它可以正常工作,但是对于大数组,它只适用于第一步。我也尝试了轴设置,但我没有机会。
如果这是我问题的唯一解决方案,我也可以使用Cython或numba。
P.S。对不起我的英语我希望你能理解一切。
答案 0 :(得分:3)
np.cross
具有axisa
,axisb
和axisc
个关键字参数,用于选择输入和输出参数中要交叉相乘的向量的位置。我想你想用:
np.cross(d2, d3, axisa=1, axisb=1, axisc=1)
如果不包含axisc=1
,则乘法的结果将位于输出数组的末尾。
此外,您可以通过执行以下操作来避免显式循环遍历torsion
数组:
torsion = np.zeros((len(d1), 1)
idx = (tb !=0)
torsion[idx] = tt[idx] / tb[idx]