Pythonでアルゴン液体の分子動力学シミュレーションを行っています。安定バージョンを実行していますが、100アトムを超えると実行速度が遅くなります。ボトルネックは、次のネストされたforループであると特定しました。これは、main.pyスクリプトから呼び出される関数内に配置された力の計算です。
def computeForce(currentPositions):
potentialEnergy = 0
force = zeros((NUMBER_PARTICLES,3))
for iParticle in range(0,NUMBER_PARTICLES-1):
for jParticle in range(iParticle + 1, NUMBER_PARTICLES):
distance = currentPositions[iParticle] - currentPositions[jParticle]
distance = distance - BOX_LENGTH * (distance/BOX_LENGTH).round()
#note: this is so much faster than scipy.dot()
distanceSquared = distance[0]*distance[0] + distance[1]*distance[1] + distance[2]*distance[2]
if distanceSquared < CUT_OFF_RADIUS_SQUARED:
r2i = 1. / distanceSquared
r6i = r2i*r2i*r2i
lennardJones = 48. * r2i * r6i * (r6i - 0.5)
force[iParticle] += lennardJones*distance
force[jParticle] -= lennardJones*distance
potentialEnergy += 4.* r6i * (r6i - 1.) - CUT_OFF_ENERGY
return(force,potentialEnergy)
大文字の変数は定数であり、config.pyファイルで定義されています。「currentPositions」は、粒子数が3の行列です。
ネストされたforループのバージョンをscipy.weaveで既に実装しました。これは、次のWebサイトから着想を得ています:http ://www.scipy.org/PerformancePython 。
しかし、私は柔軟性の喪失が好きではありません。これをforループで「ベクトル化」することに興味があります。私はそれがどのように機能するのか本当にわかりません。誰かが私にこれを教える手がかりや良いチュートリアルを教えてもらえますか?