Numpy ndarray 必須具有相同型別的所有元素,并且同一級別上的所有子陣列必須具有相同的長度。這些屬性也是 C 多維陣列的屬性。numpy ndarray 是否具有這些屬性純粹是因為它是在 C 陣列之上實作的?創建快速多維陣列實作真的需要這些屬性嗎?
uj5u.com熱心網友回復:
numpy ndarray 是否具有這些屬性純粹是因為它是在 C 陣列之上實作的?
不,在內部使用 C 并不是 Numpy 做出這個選擇的真正原因。實際上,Numpy 陣列只是內部的原始連續記憶體緩沖區(動態分配)。Numpy 實際上并沒有在自己的實作中使用 C 陣列。它只使用C 指標。視圖是參考緩沖區和舊一些元資訊(如步幅、形狀、型別等)的 Python 物件。Python 用戶總是在視圖上操作,因為無法直接讀取/寫入原始緩沖區。
實際上,在 C 中創建交錯陣列(即包含可變大小陣列的陣列)并不是很困難,但需要手動創建(即標準不直接支持)。對于 2D 鋸齒狀陣列,這通常通過分配 T* 項的陣列然后對 N 個子陣列執行 N 次分配來完成。不保證子陣列是連續存盤的。
關鍵是由于記憶體碎片/擴散和非連續性,鋸齒狀陣列效率不高。此外,Numpy 提供的許多功能對于鋸齒狀陣列來說(有效地)是不可能的。例如,為其他視圖創建子視圖會很棘手。必須重新定義在多軸(例如np.sum(2D_array, axis=0))上作業的操作,以便它對鋸齒狀陣列有意義。它還會使實施更加復雜。
因此,他們選擇不實作鋸齒狀陣列,而只實作 ND 陣列。請注意,Numpy 最初是為科學家特別是物理學家創建的,他們很少需要鋸齒狀陣列但關心高性能。鋸齒狀陣列可以通過分配 2 個 Numpy 陣列來相對有效地實作:1 個連接所有行的陣列和一個包含開始/結束偏移量的基于切片的陣列。
創建快速多維陣列實作真的需要這些屬性嗎?
具有同質型別對性能至關重要。動態打字強制對每個昂貴的專案進行型別檢查。此外,動態型別通常需要額外的昂貴間接(例如,陣列只存盤指標/參考而不是物件本身)并且對物件的訪問會導致記憶體碎片/擴散。與加法/減法/乘法等基本數值運算相比,此類運算非常昂貴。此外,物件的生命周期肯定必須像 CPython 那樣仔細控制(例如垃圾收集)。事實上,CPython 的 list 串列的行為就是這樣,而且效率很低。您可以將 Numpy 物件陣列設為 Numpy 陣列,但這也是低效的。
至于矩形陣列,它取決于用例,但這至少對于矩陣乘法和矩陣向量乘積至關重要(因為BLAS對連續陣列進行操作,行間可能有跨度),以及操作不起作用在最連續的維度上(編譯器可以通過恒定的步幅進行更積極的優化)。更不用說上面指定的額外開銷(例如額外的檢查和記憶體碎片/擴散)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/479474.html
標籤:Python C 麻木的 多维数组 numpy-ndarray
