2017-09-23 103 views
-1

所以我正在編寫一個粒子模型。該模擬將涉及創建具有諸如物種指數(用於識別粒子類型)的屬性以及3D空間中的位置/速度的許多粒子。它也將具有基於其在模擬運行期間將被計算的空間內的位置的屬性。我以前一直在使用一個巨大的numpy數組來運行這個模型,其中每一行對應一個單獨的粒子,每一列都有一個粒子屬性。我的主要問題是:如果我要創建一個類「粒子」,以便可以生成表示每個粒子的實例,那麼在計算速度方面是否存在性能問題?如果我想運行一個包含一百萬個粒子的程序,將一個大數組中的所有數字(儘管它不可​​讀)的效率更高,或者使用這個類的實例效率更高,模擬進程中的實例屬性?還是說這些類很好,但是將很多類實例存儲在Python列表/ NumPy數組中真的會減慢執行速度?另外,這個程序將與python模塊「Numba」一起使用,該模塊對數值計算有大量的優化(特別是通過類似於jitclass http://numba.pydata.org/numba-doc/latest/user/jitclass.html#numba.jitclass的東西)。但是,我不想通過在我的模擬中聲明變量導致其運行效率低下來破壞此模塊的性能優勢。Python類的性能影響:Scientific Computing

謝謝!

+0

如果可以優化類下降到結構,不會有真正使用jitclasses性能損失。也就是說,在我的領域中,大多數工作通常編寫C++擴展,然後使用像SWIG或Boost :: Python這樣的包裝將它們封裝在Python中。最終,編寫簡單的測試用例和配置文件,配置文件,配置文件。 –

+0

我不知道'numba'可以做什麼,但通常對象dtype數組比數字要慢得多。像列表一樣,這些數組值實際上是指向內存中別處的對象的指針。在https:// stackoverflow中查看我最近的回答。COM /問題/ 46350208/numpy的陣列-VS-列表換定製類。 – hpaulj

+0

創建粒子類的動機是什麼 - 更好的抽象?如果是這樣,您可以創建一個代表粒子羣體的類,並使用獲取/修改粒子信息的方法。這將使您能夠創建更高級別的抽象來處理粒子,但也會將基礎粒子數據存儲在數組中,因此您不會將數據分散到內存中。 – charlesreid1

回答

2

我以前一直使用的巨型numpy的陣列

聽起來像是一個好主意,運行這個模型。

如果我要創建一個類「粒子」,以便能夠生成表示每個粒子的實例,那麼在計算速度方面是否存在性能問題?

它可能會慢得多。

您現有的與NumPy的陣列解決方案可以代表一個大陣列中的所有的粒子:

id species x y z dx dy dz 
id species x y z dx dy dz 
id species x y z dx dy dz 

如果你改變它使用每個粒子一個類的實例,你仍然可以讓他們在與NumPy陣列(或列表),但它看起來像這樣:

object -> [id species x y z dx dy dz] 
object -> [id species x y z dx dy dz] 
object -> [id species x y z dx dy dz] 

這是您需要分配的四個N + 1對象而不是1(數組)。

我會堅持原始設計,巨型NumPy陣列,除非它引起重大問題。

+0

老實說,可能是用Cython/Swig/Boost潛入C++的最佳答案。 Jitclasses可能會更快,但我不認爲它們被視爲NumPy中的對象,這意味着指針並因此存在非連續的存儲,所以訪問速度慢,額外的開銷。一個C++擴展可以解決很多這些問題,並且實現起來很簡單,但對於這樣一個簡單的例子是不值得的(更不用說包裝問題了)。 –

0

你應該在這裏使用的結構化數據類型:

particle_dtype = np.dtype([ 
    ('id', int), 
    ('species', (np.unicode_, 16)), 
    ('pos', np.float32, 3), 
    ('vel', np.float32, 3) 
]) 

particles = np.empty(100, dtype=particle_dtype) 
particles[0]['id'] = 1 
particles['pos'] += particles['vel'] * dt