优化 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
- 不使用字典来存储
m
和 C
的值,而是将它们定义为不同的变量,并且仅在返回时才创建字典:
m = []
C = []
...
return {"m": m, "C": C}, lattice
您也可以使用 deque 而不是列表,这应该比列表更快。
当 if
语句中包含 and
条件时,如果第二个条件不影响语句的值,则不会计算第二个条件。换句话说,如果你能弄清楚哪个陈述更有可能失败并首先对其进行评估,那么你可以通过更快地失败来节省一些时间。
使用列表追加,您可以通过将追加预分配给它自己的变量来节省时间:
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)
如果您还没有尝试过分析您的代码以弄清楚什么需要时间,我建议您这样做。
- https://docs.python.org/3/library/profile.html
- How can you profile a Python script?
- https://stackify.com/how-to-use-python-profilers-learn-the-basics/
评估点 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)
我正在尝试对伊辛模型进行 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
- 不使用字典来存储
m
和C
的值,而是将它们定义为不同的变量,并且仅在返回时才创建字典:
m = []
C = []
...
return {"m": m, "C": C}, lattice
您也可以使用 deque 而不是列表,这应该比列表更快。
当
if
语句中包含and
条件时,如果第二个条件不影响语句的值,则不会计算第二个条件。换句话说,如果你能弄清楚哪个陈述更有可能失败并首先对其进行评估,那么你可以通过更快地失败来节省一些时间。使用列表追加,您可以通过将追加预分配给它自己的变量来节省时间:
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)
如果您还没有尝试过分析您的代码以弄清楚什么需要时间,我建议您这样做。
- https://docs.python.org/3/library/profile.html
- How can you profile a Python script?
- https://stackify.com/how-to-use-python-profilers-learn-the-basics/
评估点 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)