我在 Python 代码中有一个双 for 循环。我想提高执行速度,但矩阵是使用前一行和前一列的数据构建的。我该如何实现?

import numpy as np

num_rows, num_cols = 100, 5

matrix = np.zeros((num_rows, num_cols))

matrix[0, :] = np.random.rand(num_cols)
matrix[:, 0] = np.random.rand(num_rows)

coeff1 = np.random.rand(num_rows)
coeff2 = np.random.rand(num_rows)
coeff3 = np.random.rand(num_rows)

result = np.zeros_like(matrix)

for j in range(1, num_cols):
    for n in range(1, num_rows):
        
        term1 = coeff1[n] * matrix[n-1, j-1]
        term2 = coeff2[n] * matrix[n, j-1]
        term3 = coeff3[n] * matrix[n-1, j]
        
        result[n, j] = term1 + term2 + term3


最佳答案
4

使其完全矢量化:

# Vectorized calculation for each j > 0
 # Prev row, prev col (term1)
term1 = coeff1[1:, None] * matrix[:-1, :-1] 
# Current row, prev col (term2)
term2 = coeff2[1:, None] * matrix[1:, :-1]  
# Prev row, current col (term3) 
term3 = coeff3[1:, None] * matrix[:-1, 1:]  

# Summing the terms to get the result matrix (vectorized)
result[1:, 1:] = term1 + term2 + term3

使用 NumPy 的矢量化操作如下:

for j in range(1, num_cols):
    term1 = coeff1[1:] * matrix[:-1, j-1]
    term2 = coeff2[1:] * matrix[1:, j-1]
    term3 = coeff3[1:] * matrix[:-1, j]

    result[1:, j] = term1 + term2 + term3

在我的系统上这大约快了 12 倍。

2

  • 我尝试了这个解决方案,但没有得到相同的结果。


    – 

  • 1
    我可以确认,在给定的代码中,np.random.seed结果是相同的。您是否执行了其他操作?另外,请查看@Soudipta-Dutta 的答案。这可能要好得多。


    – 


公平地说,让某些东西更快的想法与 C/C++ 非常相似。但你很幸运,因为你目前正在使用numpy。我会选择

根据文档。

支持 NumPy 的 Python 优化编译器。它使用 LLVM 编译器项目从 Python 语法生成机器代码。Numba 可以编译大量以数值为中心的 Python 子集,包括许多 NumPy 函数。此外,Numba 还支持循环的自动并行化、GPU 加速代码的生成以及 ufunc 和 C 回调的创建。

一个代码片段来指导您。

import numpy as np
from numba import jit

@jit(nopython=True, parallel=True)
def numba_func(matrix, coeff1, coeff2, coeff3, result, num_rows, num_cols):
    for j in range(1, num_cols):
        for n in range(1, num_rows):
            term1 = coeff1[n] * matrix[n-1, j-1]
            term2 = coeff2[n] * matrix[n, j-1]
            term3 = coeff3[n] * matrix[n-1, j]
            result[n, j] = term1 + term2 + term3

num_rows, num_cols = 100, 5
matrix = np.zeros((num_rows, num_cols))
matrix[0, :] = np.random.rand(num_cols)
matrix[:, 0] = np.random.rand(num_rows)

coeff1 = np.random.rand(num_rows)
coeff2 = np.random.rand(num_rows)
coeff3 = np.random.rand(num_rows)

result = np.zeros_like(matrix)

# Call the function with JIT-compiled speed
numba_func(matrix, coeff1, coeff2, coeff3, result, num_rows, num_cols)

如果您想要超快,您可以尝试使用并行计算来加快该过程。

你也可以使用 numba 中的矢量化函数

参见文档 ->

你可以做这样的事情

from numba import vectorize, int32, int64, float32, float64
import numpy as np
@vectorize([your inputs])
def f(x, y):
    return x + y

你可以使用库来实现这一点

import numpy as np

# Example matrix dimensions
n = 1000

# Initialize matrices
matrix = np.zeros((n, n))

# Fill matrix using NumPy (vectorized operations)
for i in range(1, n):
    matrix[i, 0] = matrix[i - 1, 0] + 1
    for j in range(1, n):
        matrix[i, j] = matrix[i - 1, j] + matrix[i, j - 1] - matrix[i - 1, j - 1]

2

  • OP 已经在使用 NymPy!


    – 

  • 这些不是矢量化操作。


    –