我撰寫了一個方法,它接受一個整數“n”并創建一個方陣,其中每個元素的值由它們各自的 i,j 索引決定。
當我構建一個 30x30 的小矩陣時,它作業得很好,但是當我嘗試做像 1000x1000 這樣更大的東西時,它需要很長時間。有什么方法可以通過多處理加快速度嗎?
def createMatrix(n):
matrix = []
for j in range(1,n 1):
row = []
for i in range(1,n 1):
value = 1/(i j-1)
row.append(value)
matrix.append(row)
return np.array(matrix)
uj5u.com熱心網友回復:
由于 GIL,在 Python 中并行化兩個計算系結for回圈并非易事。好訊息是您的案例是完全可向量化的:
def createMatrix(n):
return 1 / (np.arange(n)[None, :] np.arange(n)[:, None] 1)
解釋:
- 本質上,您的矩陣公式是
X[row][column] = 1/(row column-1),其中行和列基于 1 np.arange(n)創建可用于行或列的范圍[None, :]并將[:, None]其轉換為二維陣列,1 x n或n x 1numpy然后廣播維度,復制行和列索引以匹配維度 - 因此,n x n在添加時隱式平鋪兩者- 因為這兩個范圍都是從 0 開始的,所以使用
1而不是-1
根據經驗,在 numpy 陣列上使用 for 回圈幾乎不是一個好主意。矢量化方法(即矩陣形式計算)要快幾個數量級。
uj5u.com熱心網友回復:
使用 fors 填充串列然后將其轉換為矩陣不是一個好主意。您可以使用 numpy 從頭開始??對您的操作進行矢量化。如果您認為給定i,j,則 M(i,j) = 1/(j i-1)考慮到兩個索引都從 1 開始。
這是我的建議:
def createMatrix2(n):
arr =np.arange(1,n 1)
xx,yy = np.meshgrid(arr,arr)
matrix = 1/(xx yy-1)
return matrix
看著 Marat 的回答,我認為他/她的更好,所以測驗了 3 種方法:
編輯:添加 wwii 方法作為 createMatrix4 (更正錯誤):
import numpy as np
from time import time
def createMatrix1(n):
matrix = []
for j in range(1,n 1):
row = []
for i in range(1,n 1):
value = 1/(i j-1)
row.append(value)
matrix.append(row)
return np.array(matrix)
def createMatrix2(n):
arr =np.arange(1,n 1)
xx,yy = np.meshgrid(arr,arr)
matrix = 1/(xx yy-1)
return matrix
def createMatrix3(n):
"""Marat's proposed matrix"""
return 1 / (1 np.arange(n)[None, :] np.arange(n)[:, None])
def createMatrix4(n):
""" wwii method"""
i,j = np.ogrid[1:n,1:n]
return 1/(i j-1)
#test all the three methods
n = 10000
t1 = time()
m1 = createMatrix1(n)
t2 = time()
m2 = createMatrix2(n)
t3 = time()
m3 = createMatrix3(n)
t4 = time()
m4 = createMatrix4(n)
t5 = time()
print(np.allclose(m1,m2))
print(np.allclose(m1,m3))
print(np.allclose(m1,m4))
print("Matrix 1 (OP): ",t2-t1)
print("Matrix 2: (mine)",t3-t2)
print("Matrix 3: (Marat)",t4-t3)
print("Matrix 4: (wwii)",t5-t4)
# the output is:
#True
#True
#True
#Matrix 1 (OP): 18.4886577129364
#Matrix 2: (mine) 1.005324363708496
#Matrix 3: (Marat) 0.43033909797668457
#Matrix 4: (wwii) 0.5138359069824219
所以 Marat 的解決方案更快。作為一般評論:
- 盡量避免fors回圈
- 將您的問題視為直接使用 numpy 陣列進行索引操作和設計操作。
最后,鑒于 Marat 的回答,我認為我的建議更易于閱讀和理解。但這只是主觀的看法
uj5u.com熱心網友回復:
您的代碼可以用另一種風格撰寫,由 numba 庫在并行無 python 模式下加速:
import numba as nb
@nb.njit("float64[:, ::1](int64)", parallel=True, fastmath=True)
def createMatrix(n):
matrix = np.empty((n, n)) # np.zeros is slower than np.empty
for j in nb.prange(1, n 1):
for i in range(1, n 1):
matrix[j - 1, i - 1] = 1 / (i j - 1)
return matrix
此解決方案將比Marat答案快3 倍以上。
基準測驗:(colab 的臨時鏈接)
n = 1000
1000 loops, best of 5: 3.52 ms per loop # Marat
1000 loops, best of 5: 1.5 ms per loop # numba accelerated with np.zeros
1000 loops, best of 5: 1.05 ms per loop # numba accelerated with np.empty
n = 3000
1000 loops, best of 5: 39.5 ms per loop
1000 loops, best of 5: 19.3 ms per loop
1000 loops, best of 5: 8.91 ms per loop
n = 5000
1000 loops, best of 5: 109 ms per loop
1000 loops, best of 5: 53.5 ms per loop
1000 loops, best of 5: 24.8 ms per loop
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/491152.html
