簡體   English   中英

時間乘法矩陣和向量

[英]time multiplying matrices and vectors

我寫了這個算法以兩種方式解決矩陣向量乘積:想象我有一個矩陣 A nxn 和一個向量 X nx1

1) 內積:Y11 = A11*X11 + A12*X21 + .... + A1n*n1 依此類推

2) 線性組合:Y = Colum1mn*X1 + Column2*X2 依此類推

我這樣做是因為我想比較誰是我嘗試過的矩陣向量乘法的最快方法

n=[10000,9000,8000,7000,6000,5000,4000,3000,2000,1500,1000,800,500,300,100]

運行算法 3 次並取 n 的每個值的平均值並得到這個圖,我是對的,內積是最快的,因為如何在內存中保存矩陣,那沒關系,但我運行了 3 次算法來繪制圖形點並得到 N=7000 的時間 > N=8000 的時間 > N=9000 的時間。 我想知道這是為什么? 我認為這可能是因為計算機會開始緩慢計算,但是如果我多次運行該算法,它會計算得更快。 但是我在前 3 次(總共 10 次)之后運行了 7 次算法並得到了大致相同的結果(這次 n=7000 時間大約是 130 秒而不是 150 但仍然是時間 7000 > 時間 8000 > 時間 9000)

這是我寫的代碼

def Lineal_C(A,x,n):
    y=np.zeros(n)    
    t = time.clock()
    for j in range(n):
       for i in range(n):
          y[i]=y[i]+A[i][j]*x[j][0]
    time_spent = time.clock() - t
    print ("%.10f sec" % (time_spent)+" n"+str(n)+" Lineal Combination ")

def Inner_P(A,x,n):
    y=np.zeros(n)
    t = time.clock()
    for i in range(0,n):
        for j in range(n):
            y[i]=y[i]+A[i][j]*x[j][0]

    time_spent = time.clock() - t
    print ("%.10f sec" % (time_spent)+" n="+str(n)+" ------MatVectFila - Producto Interno--------")

起初我認為答案可能涉及一些與數據的實際大小和基於大小的執行路徑差異有關的重要細節,但最終循環是在 Python 中進行的。 據我所知,標准的 Python 解釋器不會做任何花哨的事情(例如,沒有 JIT)。

鏈接要點的重要部分是所有計算都在單獨的非阻塞線程上執行。 即使尺寸是從最大到最小指定的,打印輸出也是從最小到最大報告的。 這是因為代碼並行啟動所有線程(好吧,快速連續),最小的線程最先完成(盡管啟動稍晚)。 這意味着最終只有大數據線程會運行,並且它們最終會相對更快。

如果您按順序運行每個數據大小,那么您永遠不會看到這些奇怪的計時效果,因為每個大小不再與其他大小“爭奪周期”。 請注意,這實際上可能是在爭奪處理器中的周期或與全局解釋器鎖爭奪解釋時間(措辭?)。

下面的代碼強制每個尺寸在運行下一個尺寸之前完成:

    for value in n_values:
       t1 = threading.Thread(target=threadss , args=(value,))
       t1.start()
       t1.join() #forces t1 to finish before the next loop iteration

在這一點上,我想我已經發現問題在於更大的尺寸稍后執行,因此可以相對更快地運行,因為它們不必與盡可能多的線程共享處理時間。 但是,如果它們同時開始,運行得更快一點不應該使某些事情總體上花費更少的時間,而只是減少每個單位大小的時間(這不是測量的)。 例如,如果您幾乎同時啟動 n=7000 和 n=8000,則 n=7000 完成后,n=8000 的計算速度應該會稍微快一些,但它的執行速度不應超過 n=7000。 所以,缺少了一些東西。

有趣的是,如果您在循環的開頭添加一個打印語句,您應該注意到循環線程幾乎按順序從小線程到大線程執行。 起初,我認為線程處理過程有些奇怪,但事實證明,真正的罪魁禍首是這一行:

matrix, vector = ranMatrix(value)

該函數調用構建了一個數字列表列表,與 numpy 之類的東西相比,這在 Python 中效率極低 - 因此這需要不可忽略的時間(這可能會因 Python 的全局解釋器鎖而加劇)。 此調用在計時器之外,並具有將較大數據循環的開始延遲到較小數據循環完成后的效果(同樣,如果您在循環開始時打印,則可見)。 因此,我對所有循環同時開始的假設是不正確的,實際上大數據循環直到較小的數據循環之后才會開始,因為這種初始化沒有定時。 所以我認為我上面的結論是正確的,只是我沒有意識到延遲啟動的重要性。

所以重申一下,當 7000 正在運行時,8000、9000 和 10000 仍在構建他們的陣列。 當 8000 正在運行時,7000 已完成(與較小的尺寸一樣),並且只有 9000 和 10000 正在構建它們的陣列。 在某些時候,每個數據點的執行速度與更大的數組/矩陣大小相比,似乎有利於更快的執行,這意味着總體執行時間會下降。 換句話說,如果總時間是 n_elements*time_per_element,如果 time_per_element 足夠快,那么即使 n_elements 增加,total_time 也會減少。

除了阻塞線程,您還可以預先初始化所有數據。 這兩個變化是:

    matrix, vector = ranMatrix(10000)
    for value in n_values:
       t1 = threading.Thread(target=threadss , args=(value,matrix,vector))
       t1.start()

def threadss(value,matrix,vector):

    threading.Thread(target=linealComb , args=(matrix , vector, value,)).start()
    threading.Thread(target=innerProduct , args=(matrix , vector, value,)).start()

由於代碼在固定大小上運行,因此矩陣和向量實際上是否更大並不重要。 這也使得更大的數據不會跑得更快。

暫無
暫無

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

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