我有一些多維資料,想知道當速度是我關注的一個(盡管不是最高)時是否應該使用 xarray。
我有一個 4D 陣列,所以它不會大到阻止我使用 numpy。坐標/索引對于一個維度至關重要,但對于所有其他維度而言并非如此。我將不得不做一些小記賬,但作為主要開發人員,這對我來說沒問題。對于在我之后繼續迭代代碼的開發人員來說,使用整數索引可能比使用基于標簽的(xarray/pandas)方法更令人困惑。無論如何,如果我很好地記錄了這個程序,我仍然可以使用 numpy。但我想使用 xarray 來提高可讀性。
實施解決方案后,我注意到下面的操作/索引將在我的機器上大約 5 秒內完成。
for isotope in isotopes:
for height in heights:
for assm in assemblies:
da.loc[dict(power=['NW','NE','SW','SE'],
assembly=assm,
height=height,
isotope=isotope)] = [3,5,1,20]
如果我在 xarray 上以基于整數的方法做同樣的事情,大約需要 2 秒。
for k,isotope in enumerate(isotopes):
for j,height in enumerate(heights):
for i,assm in enumerate(assemblies):
da[i,[-4,-3,-2,-1],j,k] = [3,5,1,20]
最后,我注意到如果我在 numpy 中執行相同的基于整數的索引,則只需不到半秒
arr = np.zeros((44,10,22,13))
for k,isotope in enumerate(isotopes):
for j,height in enumerate(heights):
for i,assm in enumerate(assemblies):
arr[i,[-4,-3,-2,-1],j,k] = [3,5,1,20]
速度不是我最關心的問題,但如果 xarray 中基于標簽的方法慢 8 倍以上,xarray 中基于整數的方法比標準的基于 numpy 整數的方法慢 4 倍,這會阻止我深入挖掘xarray 用于中等級別的多維資料。
有什么想法、建議等嗎?
uj5u.com熱心網友回復:
我們無法真正告訴您要使用哪個包,當然也不能不知道更多關于您的資料和用例的資訊。
值得一提的是,雖然 xarray 的性能與 numpy 相比總是落后,但在執行這樣的小操作時差異最為明顯。您正在使用索引在三重 for 回圈中分配少量資料,這是 xarray 的 kryptonite。如果您同時進行所有分配,您會看到懲罰顯著減少,因為索引開銷相對于底層 numpy 操作變得不那么重要。xarray 中的性能就是要了解如何最大限度地減少開銷并盡可能地利用后端的性能,同時仍然提供基于標簽的索引的便利性。
看這個簡單的例子。我創建了一個具有 100 萬個 float64 的 3-D DataArray,索引為 (x, y, z):
In [11]: da = xr.DataArray(
...: np.random.random(size=(100, 100, 100)),
...: dims=list('xyz'),
...: coords=[pd.Index([f'{d}{i}' for i in range(100)], name=d) for d in 'xyz'],
...: )
回圈遍歷 x 和 y,然后沿前四個元素賦值z會產生巨大的損失,對于相同的操作,xarray 的運行時間剛好超過 numpy 的 100 倍:
In [12]: %%time
...: for xi, x in enumerate(da.x.values):
...: for yi, y in enumerate(da.y.values):
...: da.loc[{'x': x, 'y': y, 'z': ['z0', 'z1', 'z2', 'z3']}] = [1, 2, 3, 4]
...:
CPU times: user 2.96 s, sys: 38.3 ms, total: 3 s
Wall time: 2.97 s
In [13]: %%time
...: for xi, x in enumerate(da.x.values):
...: for yi, y in enumerate(da.y.values):
...: da.values[xi, yi, :4] = [1, 2, 3, 4]
...:
CPU times: user 25.7 ms, sys: 508 μs, total: 26.3 ms
Wall time: 25.8 ms
如果重新構造相同的操作以一次分??配所有元素,xarray 的性能損失將降低到 numpy 運行時的大約 6 倍。
In [15]: %%time
...: da.loc[{'z': ['z0', 'z1', 'z2', 'z3']}] = np.tile([1, 2, 3, 4], (100, 100, 1))
...:
...:
CPU times: user 1.4 ms, sys: 675 μs, total: 2.07 ms
Wall time: 2.99 ms
In [16]: %%time
...: da.values[:, :, :4] = np.tile([1, 2, 3, 4], (100, 100, 1))
...:
...:
CPU times: user 488 μs, sys: 222 μs, total: 710 μs
Wall time: 428 μs
分配整個陣列將 xarray 的開銷減少到大約 2 倍:
In [19]: %%time
...: da.loc[{'z': da.z}] = np.tile(np.random.random(100), (100, 100, 1))
...:
...:
CPU times: user 11.2 ms, sys: 9.43 ms, total: 20.7 ms
Wall time: 20.9 ms
In [20]: %%time
...: da.values[:, :, :] = np.tile(np.random.random(100), (100, 100, 1))
...:
...:
CPU times: user 3.08 ms, sys: 4.61 ms, total: 7.7 ms
Wall time: 6.72 ms
這是否值得付出代價取決于您。但無論您選擇哪種方式,都不要使用嵌套的 for 回圈進行賦值:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/471424.html
