簡體   English   中英

為什么 numpy 在查找矩陣中的非零元素時更快?

[英]Why is numpy faster at finding non-zero elements in a matrix?

def nonzero(a):      
    row,colum = a.shape
    nonzero_row = np.array([],dtype=int)
    nonzero_col = np.array([],dtype=int)
    for i in range(0,row):
        for j in range(0,colum):
            if a[i,j] != 0:
                nonzero_row = np.append(nonzero_row,i)
                nonzero_col = np.append(nonzero_col,j)
    return (nonzero_row,nonzero_col) 

與上面的代碼相比,上面的代碼要慢得多

(row,col) = np.nonzero(edges_canny)

如果我能得到任何關於如何提高速度以及為什么 numpy 函數要快得多的指導,那就太好了?

NumPy 函數優於 Python 類型的原因有兩個:

  • 數組中的值是本機類型,而不是 Python 類型。 這意味着 NumPy 不需要經過 Python 具有的抽象層。
  • NumPy 函數(大部分)是用 C 編寫的。這實際上只在某些情況下很重要,因為很多 Python 函數也是用 C 編寫的,例如sum

在您的情況下,您也會做一些非常低效的事情:您附加到一個數組。 這是雙循環中間的一項非常昂貴的操作。 這是一個明顯的(也是不必要的)瓶頸。 只需將列表用作nonzero_rownonzero_col並且僅在返回之前將它們轉換為數組,您就會獲得驚人的加速:

def nonzero_list_based(a):      
    row,colum = a.shape
    a = a.tolist()
    nonzero_row = []
    nonzero_col = []
    for i in range(0,row):
        for j in range(0,colum):
            if a[i][j] != 0:
                nonzero_row.append(i)
                nonzero_col.append(j)
    return (np.array(nonzero_row), np.array(nonzero_col)) 

時間安排:

import numpy as np

def nonzero_original(a):      
    row,colum = a.shape
    nonzero_row = np.array([],dtype=int)
    nonzero_col = np.array([],dtype=int)
    for i in range(0,row):
        for j in range(0,colum):
            if a[i,j] != 0:
                nonzero_row = np.append(nonzero_row,i)
                nonzero_col = np.append(nonzero_col,j)
    return (nonzero_row,nonzero_col) 


arr = np.random.randint(0, 10, (100, 100))
%timeit np.nonzero(arr)
# 315 µs ± 5.39 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit nonzero_original(arr)
# 759 ms ± 12.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit nonzero_list_based(arr)
# 13.1 ms ± 492 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

即使它比 NumPy 操作慢 40 倍,它仍然比您的方法快 60 倍以上。 這里有一個重要的教訓:盡可能避免np.append


NumPy 優於替代方法的另一點是因為它們(大部分)使用最先進的方法(或“導入”它們,即 BLAS/LAPACK/ATLAS/MKL)來解決問題。 這些算法多年來(如果不是幾十年)已經針對正確性和速度進行了優化。 您不應該期望找到更快甚至類似的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM