【问题标题】:Optimizing python code monte carlo simulation优化python代码蒙特卡罗模拟
【发布时间】:2021-05-24 08:16:14
【问题描述】:

我正在尝试对 Ising 模型进行蒙特卡罗模拟。由于我必须执行许多蒙特卡罗步骤,我的代码运行速度很慢。我正在尝试优化我的代码以使其更快。我已经优化了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

【问题讨论】:

标签: python optimization montecarlo


【解决方案1】:
  1. 不要使用 dict 来存储 mC 的值,而是将它们定义为不同的变量,并仅在返回时创建 dict:
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)

【讨论】:

  • 我测试了将 .append 预分配到一个变量的时间,我在 8100 万次追加中节省了 2μs,但不幸的是,不确定这是否会节省那么多时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 1970-01-01
  • 2013-01-02
  • 2019-01-21
  • 1970-01-01
  • 1970-01-01
  • 2012-04-26
相关资源
最近更新 更多