我想創建一個用于多智能體模擬的程式,我正在考慮是否應該使用 NumPy 或 numba 來加速計算。基本上,我需要一個類來存盤代理的狀態,并且我將擁有超過 1000 個此類的實體。在每個時間步,我將對所有實體執行不同的計算。我正在考慮兩種方法:
Numpy矢量化:
有 1 個具有多個 NumPy 陣列的類,用于存盤所有代理的狀態。因此,在模擬程序中,我始終只有 1 個類實體。通過這種方法,我可以簡單地使用 NumPy 向量化來執行計算。但是,這將使特定代理的運行功能變得困難,我需要一個額外的類來存盤每個代理的索引。
Class agent:
def __init__(self):
self.A = np.zeros(1000)
self.B = np.zeros(1000)
def timestep(self):
return self.A self.B
Numba jit 類:
使用 numba jitclass 裝飾器編譯代碼。使用這種方法,我可以應用更標準的 OOP 格式代碼,因為一個類實體代表一個代理。但是,我不確定回圈通過多個 jitclass 實體(比如 1000 和更多)的性能。
@jitclass
class agent:
def __init__(self):
self.A = 0
self.B = 0
def timestep(self):
return self.A self.B
我想知道哪種方法更快。
uj5u.com熱心網友回復:
這個問題被稱為“AoS VS SoA”,其中 AoS 表示結構陣列,SoA 表示陣列結構。您可以在此處找到有關此的一些資訊。SoA 的用戶友好性不如 AoS,但通常效率更高。當您的代碼可以從使用SIMD 指令中受益時尤其如此. 當您處理許多大陣列(例如 >=8 個大陣列)或執行許多標量隨機記憶體訪問時,AoS 和 SoA 都不是有效的。在這種情況下,最好的解決方案是使用小陣列結構的陣列 (AoSoA),以便更好地使用 CPU 快取,同時仍然能夠從 SIMD 中受益。然而,AoSoA 是繁瑣的,因為復雜性對于非平凡演算法的代碼非常重要。請注意,訪問的欄位數量在選擇最佳解決方案時也很重要(例如,如果經常讀取一個欄位,那么 SoA 是完美的)。
部分原因是,在性能方面,OOP 通常相當糟糕。另一個原因是經常使用虛擬呼叫和多型性,但并不總是需要它。OOP 代碼往往會導致大量快取未命中,并且優化大量使用 OOP 的大型代碼通常是一團糟(這有時會導致重寫目標軟體的很大一部分或代碼變得非常慢)。為了解決這個問題,可以使用面向資料的設計。這種方法已成功地用于大幅加速從視頻游戲(例如Unity)到 Web 瀏覽器渲染器(例如Chrome )的大型代碼庫) 甚至關系資料庫。在高性能計算 (HPC) 中,OOP 通常很少使用。面向物件的設計與使用 SoA 而不是 AoS 有很大關系,因此可以更好地使用快取并從 SIMD 中受益。有關更多資訊,請閱讀此相關帖子。
最后,我建議您在您的情況下使用第一個代碼(SoA)(因為您只有兩個陣列并且它們不是那么大)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/424185.html
上一篇:將特征添加到必須使用轉換公式映射其分類值的“數字”資料集
下一篇:更改np陣列Python中的值
