我有使用時間積分計算的軌道。這些軌道具有(x, y)每個位置的坐標。這種軌道的一個例子可以在下圖中看到:

現在將這些陣列用于 x 和 y,需要構造以下系列:

這實際上意味著,一個系列,其中 0 表示 x 在時間t_n和1 之間t_n 1改變符號 1 表示 y 在t_n和之間改變符號t_n 1。對于上圖,該系列將如下所示:Pxy[n] = 1 0 1 0 1 0 ...
目前我找到了多種解決方案。但是在我使用的大型資料集上它們都非常慢。上面顯示的示例軌道的 x 和 y 坐標陣列有 10,000,000 個元素。它需要這么多元素,因為要足夠準確,積分演算法中的時間步長需要非常小。我能想出的最快演算法運行大約需要 5.3 秒。然而,同樣的演算法需要針對不同的軌道運行 100 多次。這意味著這將需要很長時間。
我基本上有兩種計算方法:第一種演算法基于這個問題:“有效地檢測 python 中的符號變化”并使用 numpy:
def calc_Pxy():
Pxy = np.full(x.shape, -1)
Pxy[np.where(np.diff(np.signbit(x)))] = 0
Pxy[np.where(np.diff(np.signbit(y)))] = 1
return Pxy[Pxy >= 0]
第二種解決方案只使用一個簡單的 for 回圈:
def calc_Pxy():
Pxy = []
for n, [xn, yn] in enumerate(zip(x[:-1], y[:-1])):
if xn * x[n 1] < 0:
Pxy.append(0)
if yn * y[n 1] < 0:
Pxy.append(1)
return np.array(Pxy)
!見編輯!在測量了這兩種方法的性能之后,似乎第一種使用 numpy 的方法比普通的 for 回圈慢了 2.5 倍。我的第一個問題是,為什么會這樣?是因為它正在重塑陣列,這需要時間,因為需要創建新陣列?第二個問題是,我怎樣才能比 for 回圈更快?
最后,第一個 numpy 方法的另一個問題是,當 x 和 y 在同一時間步長變化時,在第一個示例中僅記錄 1 個交叉點,而在第二個示例中,在這些情況下總是首先將 x 和然后是 y 交叉口。我更喜歡這樣,因為這樣不會丟失任何資料。
任何關于如何提高性能的想法將不勝感激。
編輯:在對大型資料集進行測驗后,如果資料集的大小增加,numpy 方法似乎會變得更快。我最初的測驗是基于一個包含 20 個值的小型資料集,但是對于 1,000,000 個值,numpy 方式更快。但是,我仍在尋找一種使該方法的行為與 for 回圈相同的方法,并且當然也歡迎任何進一步的速度改進。
uj5u.com熱心網友回復:
結合方法1和2的思路:
def calc_Pxy3():
Pxy = []
for [xn, yn] in zip(np.diff(np.signbit(x)), np.diff(np.signbit(y))):
if xn:
Pxy.append(0)
if yn:
Pxy.append(1)
return np.array(Pxy)
與方法 2 相比,我們得到了大約 5 倍的加速(但仍然比方法 1 慢 5 倍)。
Results for n = 10_000_000 random x/y values:
%timeit calc_Pxy1() # numpy
253 ms ± 3.08 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit calc_Pxy2() # simple loop
10.8 s ± 124 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit calc_Pxy3()
2.18 s ± 17.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
uj5u.com熱心網友回復:
你可以簡單地使用numba:
import numba
@numba.njit
def calc_Pxy_numba(x, y):
Pxy = []
for n, [xn, yn] in enumerate(zip(x[:-1], y[:-1])):
if xn * x[n 1] < 0:
Pxy.append(0)
if yn * y[n 1] < 0:
Pxy.append(1)
return np.array(Pxy)
請注意,我避免使用這種方法使用全域變數。
uj5u.com熱心網友回復:
為了獲得更好的性能,最好不要使用append,你可以試試這個:
(如果你已經安裝了numba,你可以匯入numba和撰寫@numba.njit)
def calc_Pxy4(x, y):
Pxy = np.full(len(x) len(y), -1)
idx = 0
for xn, yn in zip(x[:-1] * x[1:] , y[:-1] * y[1:]):
if xn < 0:
Pxy[idx] = 0
idx = 1
if yn < 0:
Pxy[idx] = 1
idx = 1
return Pxy[:idx]
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/485056.html
上一篇:多執行緒鎖
下一篇:將2D陣列堆疊成3D陣列
