真的有可能讓這個運行得更快嗎?我需要獲得大小為 4*Lx(用于計算伊辛模型中的能量)的所有可能網格的一半(所有元素可以是 -1 或 1)。
def get_grid(Lx):
a = list()
count = 0
t = list(product([1,-1], repeat=Lx))
for i in range(len(t)):
for j in range(len(t)):
for k in range(len(t)):
for l in range(len(t)):
count = 1
a.append([t[i], t[j], t[k], t[l]])
if count == 2**(Lx*4)/2:
return np.array(a)
Tried using numba, but that didn't work out.
uj5u.com熱心網友回復:
首先,Numba 不喜歡串列。如果你想要一個高效的代碼,那么你需要對陣列進行操作(除非你真的不知道運行時的大小并且估計它很難/很慢)。這里輸出陣列的大小是已知的,所以最好預先分配它然后填充它。Numba 不喜歡像生成器這樣的高級功能,您應該更喜歡使用速度更快的基本回圈(只要它們在 JITed 函式中執行)。笛卡爾積可以被基于遞增整數的位的陣列的有效計算所取代。整個計算主要是記憶體限制的,所以最好使用像這樣的小整數資料型別uint8這在 RAM 中占用的空間少了 4 倍(因此填充速度快了約 4 倍)。這是結果代碼:
import numpy as np
import numba as nb
@nb.njit('int8[:,:,:](int64,)')
def get_grid_numba(Lx):
t = np.empty((2**Lx, Lx), dtype=np.int8)
for i in range(2**Lx):
for j in range(Lx):
t[i, Lx-1-j] = 1 - 2 * ((i >> j) & 1)
outSize = 2**(Lx*4 - 1)
out = np.empty((outSize, 4, Lx), dtype=np.int8)
cur = 0
for i in range(len(t)):
for j in range(len(t)):
for k in range(len(t)):
for l in range(len(t)):
out[cur, 0, :] = t[i, :]
out[cur, 1, :] = t[j, :]
out[cur, 2, :] = t[k, :]
out[cur, 3, :] = t[l, :]
cur = 1
if cur == outSize:
return out
return out
對于Lx=4,初始代碼需要 66.8 毫秒,而此 Numba 代碼在我的 i5-9600KF 處理器上需要 0.36 毫秒。因此速度提高了 185 倍。
請注意,輸出陣列的大小呈指數增長得非常快。對于Lx=7,輸出形狀為(134217728, 4, 7)并且需要 3.5 GiB 的 RAM。Numba 代碼需要 2.47 秒來生成它,即 1.4 GiB/s。如果這對你來說還不夠,那么你可以撰寫從 Lx=1 到 Lx=8 的具體實作,使用回圈來out分配切片,甚至使用多執行緒來實作 Lx>=5。對于小陣列,可以預先計算一次。這應該快一個數量級。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/535755.html
標籤:Python表现循环
下一篇:在Web上正確使用SVG
