- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题:我想用 np.einsum
加速包含大量乘积和求和的 python 循环。 ,但我也愿意接受任何其他解决方案。
我的函数采用形状为 (n,n,3) 的向量配置 S(我的情况:n=72)并对 N*N 点的相关函数进行傅立叶变换。相关函数定义为每个向量与其他向量的乘积。这乘以向量位置乘以 kx 和 ky 值的余弦函数。各岗位i,j
最后相加得到 k 空间中的一分 p,m
:
def spin_spin(S,N):
n= len(S)
conf = np.reshape(S,(n**2,3))
chi = np.zeros((N,N))
kx = np.linspace(-5*np.pi/3,5*np.pi/3,N)
ky = np.linspace(-3*np.pi/np.sqrt(3),3*np.pi/np.sqrt(3),N)
x=np.reshape(triangular(n)[0],(n**2))
y=np.reshape(triangular(n)[1],(n**2))
for p in range(N):
for m in range(N):
for i in range(n**2):
for j in range(n**2):
chi[p,m] += 2/(n**2)*np.dot(conf[i],conf[j])*np.cos(kx[p]*(x[i]-x[j])+ ky[m]*(y[i]-y[j]))
return(chi,kx,ky)
numpy
的内置 FFT ,因为我的三角形网格,所以我需要一些其他的选择来减少这里的计算成本。
np.einsum
功能。计算每个向量与每个向量的乘积是通过以下方式完成的:
np.einsum('ij,kj -> ik',np.reshape(S,(72**2,3)),np.reshape(S,(72**2,3)))
np.cos
中的项。 .在这里,我想计算形状列表 (100,1) 与向量位置之间的乘积(例如
np.shape(x)=(72**2,1)
)。特别是我真的不知道如何用
np.einsum
实现x 方向和y 方向的距离。 .
np.ones((72,72,3)
或者您以随机向量为例:
def spherical_to_cartesian(r, theta, phi):
'''Convert spherical coordinates (physics convention) to cartesian coordinates'''
sin_theta = np.sin(theta)
x = r * sin_theta * np.cos(phi)
y = r * sin_theta * np.sin(phi)
z = r * np.cos(theta)
return x, y, z # return a tuple
def random_directions(n, r):
'''Return ``n`` 3-vectors in random directions with radius ``r``'''
out = np.empty(shape=(n,3), dtype=np.float64)
for i in range(n):
# Pick directions randomly in solid angle
phi = random.uniform(0, 2*np.pi)
theta = np.arccos(random.uniform(-1, 1))
# unpack a tuple
x, y, z = spherical_to_cartesian(r, theta, phi)
out[i] = x, y, z
return out
S = np.reshape(random_directions(72**2,1),(72,72,3))
spin_spin
中将其整形回 (72**2,3) 形状。)
def triangular(nsize):
'''Positional arguments of the spin configuration'''
X=np.zeros((nsize,nsize))
Y=np.zeros((nsize,nsize))
for i in range(nsize):
for j in range(nsize):
X[i,j]+=1/2*j+i
Y[i,j]+=np.sqrt(3)/2*j
return(X,Y)
最佳答案
优化 Numba 实现
您代码中的主要问题是调用外部 BLAS 函数 np.dot
反复极小数据。在这段代码中,只计算一次会更有意义,但是如果您必须在循环中进行计算,请编写一个 Numba 实现。 Example
优化功能(蛮力)
import numpy as np
import numba as nb
@nb.njit(fastmath=True,error_model="numpy",parallel=True)
def spin_spin(S,N):
n= len(S)
conf = np.reshape(S,(n**2,3))
chi = np.zeros((N,N))
kx = np.linspace(-5*np.pi/3,5*np.pi/3,N).astype(np.float32)
ky = np.linspace(-3*np.pi/np.sqrt(3),3*np.pi/np.sqrt(3),N).astype(np.float32)
x=np.reshape(triangular(n)[0],(n**2)).astype(np.float32)
y=np.reshape(triangular(n)[1],(n**2)).astype(np.float32)
#precalc some values
fact=nb.float32(2/(n**2))
conf_dot=np.dot(conf,conf.T).astype(np.float32)
for p in nb.prange(N):
for m in range(N):
#accumulating on a scalar is often beneficial
acc=nb.float32(0)
for i in range(n**2):
for j in range(n**2):
acc+= conf_dot[i,j]*np.cos(kx[p]*(x[i]-x[j])+ ky[m]*(y[i]-y[j]))
chi[p,m]=fact*acc
return(chi,kx,ky)
@nb.njit()
def precalc(S):
#There may not be all redundancies removed
n= len(S)
conf = np.reshape(S,(n**2,3))
conf_dot=np.dot(conf,conf.T)
x=np.reshape(triangular(n)[0],(n**2))
y=np.reshape(triangular(n)[1],(n**2))
x_s=set()
y_s=set()
for i in range(n**2):
for j in range(n**2):
x_s.add((x[i]-x[j]))
y_s.add((y[i]-y[j]))
x_arr=np.sort(np.array(list(x_s)))
y_arr=np.sort(np.array(list(y_s)))
conf_dot_sel=np.zeros((x_arr.shape[0],y_arr.shape[0]))
for i in range(n**2):
for j in range(n**2):
ii=np.searchsorted(x_arr,x[i]-x[j])
jj=np.searchsorted(y_arr,y[i]-y[j])
conf_dot_sel[ii,jj]+=conf_dot[i,j]
return x_arr,y_arr,conf_dot_sel
@nb.njit(fastmath=True,error_model="numpy",parallel=True)
def spin_spin_opt_2(S,N):
chi = np.empty((N,N))
n= len(S)
kx = np.linspace(-5*np.pi/3,5*np.pi/3,N)
ky = np.linspace(-3*np.pi/np.sqrt(3),3*np.pi/np.sqrt(3),N)
x_arr,y_arr,conf_dot_sel=precalc(S)
fact=2/(n**2)
for p in nb.prange(N):
for m in range(N):
acc=nb.float32(0)
for i in range(x_arr.shape[0]):
for j in range(y_arr.shape[0]):
acc+= fact*conf_dot_sel[i,j]*np.cos(kx[p]*x_arr[i]+ ky[m]*y_arr[j])
chi[p,m]=acc
return(chi,kx,ky)
@nb.njit()
def precalc(S):
#There may not be all redundancies removed
n= len(S)
conf = np.reshape(S,(n**2,3))
conf_dot=np.dot(conf,conf.T)
x=np.reshape(triangular(n)[0],(n**2))
y=np.reshape(triangular(n)[1],(n**2))
x_s=set()
y_s=set()
for i in range(n**2):
for j in range(n**2):
x_s.add((x[i]-x[j]))
y_s.add((y[i]-y[j]))
x_arr=np.sort(np.array(list(x_s)))
y_arr=np.sort(np.array(list(y_s)))
conf_dot_sel=np.zeros((x_arr.shape[0],y_arr.shape[0]))
for i in range(n**2):
for j in range(n**2):
ii=np.searchsorted(x_arr,x[i]-x[j])
jj=np.searchsorted(y_arr,y[i]-y[j])
conf_dot_sel[ii,jj]+=conf_dot[i,j]
return x_arr,y_arr,conf_dot_sel
@nb.njit(fastmath=True,error_model="numpy",parallel=True)
def spin_spin_opt_2(S,N):
chi = np.empty((N,N))
n= len(S)
kx = np.linspace(-5*np.pi/3,5*np.pi/3,N)
ky = np.linspace(-3*np.pi/np.sqrt(3),3*np.pi/np.sqrt(3),N)
x_arr,y_arr,conf_dot_sel=precalc(S)
fact=2/(n**2)
for p in nb.prange(N):
for m in range(N):
acc=nb.float32(0)
for i in range(x_arr.shape[0]):
for j in range(y_arr.shape[0]):
acc+= fact*conf_dot_sel[i,j]*np.cos(kx[p]*x_arr[i]+ ky[m]*y_arr[j])
chi[p,m]=acc
return(chi,kx,ky)
#brute-force
%timeit res=spin_spin(S,100)
#48 s ± 671 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#new version
%timeit res_2=spin_spin_opt_2(S,100)
#5.33 s ± 59.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit res_2=spin_spin_opt_2(S,1000)
#1min 23s ± 2.43 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
import numba as nb
import numpy as np
@nb.njit(fastmath=True)
def foo(n):
x = np.empty(n*8, dtype=np.float64)
ret = np.empty_like(x)
for i in range(ret.size):
ret[i] += np.cos(x[i])
return ret
foo(1000)
if 'intel_svmlcc' in foo.inspect_llvm(foo.signatures[0]):
print("found")
else:
print("not found")
#found
not found
阅读
this link.它应该可以在 Linux 和 Windows 上运行,但我还没有在 macOS 上测试过。
关于python - python中FFT的循环加速(使用 `np.einsum`),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60934744/
我有 2 个数组,其中一个的大小为: A = np.random.uniform(size=(48, 1000000, 2)) 另一个是 B = np.random.uniform(size=(48)
似乎是 numpy 的 einsum功能不适用于 scipy.sparse矩阵。有没有其他方法可以做这些事情einsum可以处理稀疏矩阵吗? 回应@eickenberg 的回答:我想要的特定 eins
我有以下张量执行, np.einsum('k,pjqk,yzjqk,yzk,ipqt->it', A, B, C, D, E) 而且我注意到,当“z”或“q”在维度上扩展时,执行时间确实受到了影响,尽
考虑下面的 3 个数组: np.random.seed(0) X = np.random.randint(10, size=(4,5)) W = np.random.randint(10, size=
我有一个形状为 (n, n) 的矩阵 A 和另一个形状为 (p, n) 的矩阵 b。我需要得到一个矩阵 C 使得 C[i] = (A * b[i, np.newaxis, :]) * b[i, :,
随着最近对 Numpy (1.14) 的更新,我发现它破坏了我的整个代码库。这是基于将默认的 numpy einsum 优化参数从 False 更改为 True。 因此,以下基本操作现在失败了: a
我已经搜索了一种解决方案,使用 einsum 确定行数不相等但列数相等的 numpy 数组的距离。我尝试了各种组合,但唯一能成功的方法是使用以下代码。我显然遗漏了一些东西,文献和众多线程并没有让我更接
我很熟悉einsum在纽比的运作方式。pytorch也提供了类似的功能:torch.einsum()。在功能和性能方面有什么相同点和不同点?在Py火炬文档中提供的信息相当稀少,没有提供任何关于这方面的
我一直在尝试调试某个模型,该模型在重复几次的层中使用 torch.einsum 运算符。 在尝试分析训练期间模型的 GPU 内存使用情况时,我注意到某个 Einsum 操作显着增加了内存使用量。我正在
我正在尝试将三个数组 (A x B x A) 与维度 (19000, 3) x (19000, 3, 3) x (19000, 3) 相乘,这样最后我得到一个大小为 (19000) 的一维数组,所以我
我正在尝试潜入 einsum符号。此 question and answers帮了我很多。 但是现在我不能掌握einsum的机器计算外积时: x = np.array([1, 2, 3]) y = n
想象一下,我有整数,n,q和具有这些维度的向量/数组: import numpy as np n = 100 q = 102 A = np.random.normal(size=(n,n)) B =
我有两个包含兼容矩阵的 numpy 数组,想计算使用 numpy.einsum 的元素明智的外积.数组的形状是: A1 = (i,j,k) A2 = (i,k,j) 因此数组分别包含 i 个形状为 (
我想使用类似 np.dot 或(最好)np.einsum 的东西来有效地执行它们相同的功能,但使用备用 ufunc 而不是 np.multiply。例如,考虑这两个数组: >>> a array([[
我有两个包含兼容矩阵的 numpy 数组,想计算使用 numpy.einsum 的元素明智的外积.数组的形状是: A1 = (i,j,k) A2 = (i,k,j) 因此数组分别包含 i 个形状为 (
为什么这些输出不同?这是有意的行为吗?我使用的是 tensorflow 1.12 import tensorflow as tf matrix = tf.constant([[1, 2, 3],
我有以下 Einstein Sum (einsum) 表达式, import numpy as np x = np.random.rand(1,8,2,8,10) y = np.random.rand
是否有一种优雅的方法可以根据 einsum 的输入参数预先计算 np.einsum 结果的形状(无需运行计算)? # Given a, b and signature with # a.shape =
我已阅读 einsum manual和 ajcr 的 basic introduction 我在非编码环境中对爱因斯坦求和的经验为零,尽管我尝试通过一些互联网研究来弥补这一点(将提供链接,但还没有超过
我尝试寻找答案,但找不到我需要的东西。如果这是一个重复的问题,我们深表歉意。 假设我有一个形状为 (n, n*m) 的二维数组。我想要做的是这个数组与其转置的外部总和,从而产生形状为 (n*m, n*
我是一名优秀的程序员,十分优秀!