gpt4 book ai didi

python - 使用 numpy.tensordot 替换嵌套循环

转载 作者:太空宇宙 更新时间:2023-11-03 11:41:14 25 4
gpt4 key购买 nike

我有一段代码,但我想提高性能。我的代码是:

lis = []
for i in range(6):
for j in range(6):
for k in range(6):
for l in range(6):
lis[i][j] += matrix1[k][l] * (2 * matrix2[i][j][k][l] - matrix2[i][k][j][l])
print(lis)

matrix2 是一个 4 维 np 数组,matrix1 是一个二维数组。

我想通过使用 np.tensordot(matrix1, matrix2) 来加速这段代码,但后来我迷路了。

最佳答案

你可以只使用 jit-compiler

您的解决方案一点也不差。我唯一改变的是索引和可变循环范围。如果你有 numpy 数组和过度循环,你可以使用编译器 ( Numba ),这是一件非常简单的事情。

import numba as nb
import numpy as np
#The function is compiled only at the first call (with using same datatypes)
@nb.njit(cache=True) #set cache to false if copying the function to a command window
def almost_your_solution(matrix1,matrix2):
lis = np.zeros(matrix1.shape,np.float64)
for i in range(matrix2.shape[0]):
for j in range(matrix2.shape[1]):
for k in range(matrix2.shape[2]):
for l in range(matrix2.shape[3]):
lis[i,j] += matrix1[k,l] * (2 * matrix2[i,j,k,l] - matrix2[i,k,j,l])

return lis

关于代码简单性,我更喜欢 hpaulj 的 einsum 解决方案,而不是上面显示的解决方案。在我看来,tensordot 解决方案并不那么容易理解。但这是一个品味问题。

比较性能

我用于比较的 hpaulj 函数:

def hpaulj_1(matrix1,matrix2):
matrix3 = 2*matrix2-matrix2.transpose(0,2,1,3)
return np.einsum('kl,ijkl->ij', matrix1, matrix3)

def hpaulj_2(matrix1,matrix2):
matrix3 = 2*matrix2-matrix2.transpose(0,2,1,3)
(matrix1*matrix3).sum(axis=(2,3))
return np.tensordot(matrix1, matrix3, [[0,1],[2,3]])

非常短的数组给出:

matrix1=np.random.rand(6,6)
matrix2=np.random.rand(6,6,6,6)

Original solution: 2.6 ms
Compiled solution: 2.1 µs
Einsum solution: 8.3 µs
Tensordot solution: 36.7 µs

更大的数组给出:

matrix1=np.random.rand(60,60)
matrix2=np.random.rand(60,60,60,60)

Original solution: 13,3 s
Compiled solution: 18.2 ms
Einsum solution: 115 ms
Tensordot solution: 180 ms

结论

编译将计算速度提高了大约 3 个数量级,并且大大优于所有其他解决方案。

关于python - 使用 numpy.tensordot 替换嵌套循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48996893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com