我嘗試了一個簡單的代碼來并行化一個帶有 numba 和 prange 的回圈。但是由于某種原因,當我使用更多執行緒而不是更快時,它會變慢。為什么會這樣?(cpu ryzen 7 2700x 8核16執行緒3.7GHz)
from numba import njit, prange,set_num_threads,get_num_threads
@njit(parallel=True,fastmath=True)
def test1():
x=np.empty((10,10))
for i in prange(10):
for j in range(10):
x[i,j]=i j
Number of threads : 1
897 ns ± 18.3 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 2
1.68 μs ± 262 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 3
2.4 μs ± 163 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 4
4.12 μs ± 294 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 5
4.62 μs ± 283 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 6
5.01 μs ± 145 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 7
5.52 μs ± 194 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 8
4.85 μs ± 140 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 9
6.47 μs ± 348 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 10
6.88 μs ± 120 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 11
7.1 μs ± 154 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 12
7.47 μs ± 159 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 13
7.91 μs ± 160 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 14
9.04 μs ± 472 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 15
9.74 μs ± 581 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
Number of threads : 16
11 μs ± 967 ns per loop (mean ± std. dev. of 10 runs, 100000 loops each)
uj5u.com熱心網友回復:
這是完全正常的。Numba 需要創建執行緒并在它們之間分配作業,以便它們可以并行執行計算。Numba 可以使用不同的執行緒后端。默認情況下通常是OpenMP,默認的 OpenMP 實作應該是 IOMP(ICC/Clang 的 OpenMP 運行時),它只嘗試創建一次執行緒。盡管如此,在執行緒之間共享作業比迭代超過 100 個值要慢得多。現代主流處理器應該能夠在不到 0.1-0.2 us 的時間內依次執行 2 個嵌套回圈。Numba 也應該能夠展開兩個回圈. Numba 函式開銷通常也約為幾百納秒。Numpy 陣列的分配應該比實際回圈慢得多。此外,即使之前的開銷可以忽略不計,還有其他開銷會導致此代碼在使用多個執行緒時顯著變慢。例如,錯誤共享導致寫入大部分被序列化,因此比使用一個 1 唯一執行緒完成寫入要慢(因為在 x86-64 平臺上的 LLC 上運行的快取線彈跳效應)。
請注意,創建執行緒的時間通常明顯超過 1 us,因為需要進行系統呼叫。
簡而言之:當要做的作業足夠大并且可以有效地并行化時,使用執行緒。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/491150.html
