优化 python 代码 monte carlo 模拟

Optimizing python code monte carlo simulation

我正在尝试对伊辛模型进行 Monte Carlo 模拟。由于我必须执行许多 monte carlo 个步骤,我的代码运行很慢。我正在尝试优化我的代码以使其更快。我已经优化了 metropolis() 函数,但我不知道如何优化我的 simulation() 函数。我试过列表推导式,但想不出一个聪明的方法来使用它。任何提示和帮助将不胜感激。

下面是我的代码。


def simulation(MCS, T, lattice, k0):

    values = {"m" : [], "C" : []}
    
    for n in range(MCS):
        
        lattice = metropolis(lattice, T_reduced)

        if n >= k0 and n % 1000 == 0:
            # keep track on values
            values["m"].append(some_function(lattice))
            values["C"].append(some_function(lattice))

    return values, lattice
  1. 不使用字典来存储 mC 的值,而是将它们定义为不同的变量,并且仅在返回时才创建字典:
m = []
C = []
...
return {"m": m, "C": C}, lattice

您也可以使用 deque 而不是列表,这应该比列表更快。

  1. if 语句中包含 and 条件时,如果第二个条件不影响语句的值,则不会计算第二个条件。换句话说,如果你能弄清楚哪个陈述更有可能失败并首先对其进行评估,那么你可以通过更快地失败来节省一些时间。

  2. 使用列表追加,您可以通过将追加预分配给它自己的变量来节省时间:

m = []
C = []
app_m = m.append
app_C = C.append
    for i in range(r):
        if i % 3 == 0:
            app_m(i)
            app_C(i)

如果您还没有尝试过分析您的代码以弄清楚什么需要时间,我建议您这样做。

评估点 1-3 的脚本:

import timeit
from collections import deque

# for range
r = 20000
# timeit n times
ntimes = 500

def dicts():
    d = {"m": [], "C": []}
    for i in range(r):
        if i % 3 == 0:
            d["m"].append(i)
            d["C"].append(i)
    return d

def lists():
    m = []
    C = []
    for i in range(r):
        if i % 3 == 0:
            m.append(i)
            C.append(i)
    return {"m": m, "C": C}

def deques():
    m = deque(maxlen=r)
    C = deque(maxlen=r)
    for i in range(r):
        if i % 3 == 0:
            m.append(i)
            C.append(i)
    return {"m": m, "C": C}

t1 = timeit.timeit(dicts, number=ntimes)
t2 = timeit.timeit(lists, number=ntimes)
t3 = timeit.timeit(deques, number=ntimes)

print("dicsts", t1)
print("lists ", t2)
print("deques", t3)

def order1():
    m = []
    C = []
    for i in range(r):
        if i % 2 == 0 and i % 5 == 0:
            m.append(i)
            C.append(i)
    return {"m": m, "C": C}

def order2():
    m = []
    C = []
    for i in range(r):
        if i % 5 == 0 and i % 2 == 0:
            m.append(i)
            C.append(i)
    return {"m": m, "C": C}

t1 = timeit.timeit(order1, number=ntimes)
t2 = timeit.timeit(order2, number=ntimes)

print("order1", t1)
print("order2", t2)

def listsappend():
    m = []
    C = []
    app_m = m.append
    app_C = C.append
    for i in range(r):
        if i % 3 == 0:
            app_m(i)
            app_C(i)
    return {"m": m, "C": C}

t1 = timeit.timeit(lists, number=ntimes)
t2 = timeit.timeit(listsappend, number=ntimes)

print("normal", t1)
print("predef", t2)