Python优化问题?
好吧,我最近做了这个作业(别担心,我已经做了,但是用c++),但是我很好奇我怎么能用python来做。问题是大约有两个光源发出光。我不会详细讨论这些 下面是代码(我在后面的部分中对其进行了一些优化): 我已经设法优化了它的大部分,但是在与2 for-s的部分中仍然存在巨大的性能差距,而且我似乎想不出一种方法来绕过使用普通阵列操作的方法。。。我愿意接受建议:D 编辑: 根据Vlad的建议,我将发布问题的详细信息: 有2个光源,每个光源以正弦波的形式发光: E1=E0*sin(ω1*time+phi01) E2=E0*sin(ω2*time+phi02) 我们考虑Ωa1=Ωa2=ω=2×π/t和pI001=pI002=pII0。 通过将x1视为距平面上某点的第一个光源的距离,该点的光强为 Ep1=E0*sin(ω*时间-2*PI*x1/lambda+phi0) 哪里 λ=光速*T(振荡周期) 考虑到平面上的两个光源,公式变为 Ep=2*E0*cos(PI*(x2-x1)/lambda)sin(omegatime-PI*(x2-x1)/lambda+phi0) 从中我们可以看出,当 (x2-x1)/lambda=(2*k)*PI/2 最短时间 (x2-x1)/lambda=(2*k+1)*PI/2 并且在这两者之间变化,其中k是一个整数 对于给定的时刻,给定光源的坐标,对于已知的λ和E0,我们必须制作一个程序来绘制光线的外观Python优化问题?,python,optimization,numpy,for-loop,physics,Python,Optimization,Numpy,For Loop,Physics,好吧,我最近做了这个作业(别担心,我已经做了,但是用c++),但是我很好奇我怎么能用python来做。问题是大约有两个光源发出光。我不会详细讨论这些 下面是代码(我在后面的部分中对其进行了一些优化): 我已经设法优化了它的大部分,但是在与2 for-s的部分中仍然存在巨大的性能差距,而且我似乎想不出一种方法来绕过使用普通阵列操作的方法。。。我愿意接受建议:D 编辑: 根据Vlad的建议,我将发布问题的详细信息: 有2个光源,每个光源以正弦波的形式发光: E1=E0*sin(ω1*time+phi
我认为我已经尽可能地优化了这个问题…我想到的唯一变化是将一些操作移出循环:
for i in xrange(width):
if i%(width/10)==0:
print i,
if i%20==0:
print '.',
arri = arr[i]
is1x = i - s1x
is2x = i - s2x
for j in xrange(height):
d1 = hy(is1x,j-s1y)
d2 = hy(is2x,j-s2y)
arri[j] = abs(d1-d2)
不过,如果有改进的话,可能会很小。列表理解比循环快得多。例如,代替
for j in xrange(height):
d1 = hy(i-s1x,j-s1y)
d2 = hy(i-s2x,j-s2y)
arr[i][j] = abs(d1-d2)
你会写信的
arr[i] = [abs(hy(i-s1x,j-s1y) - hy(i-s2x,j-s2y)) for j in xrange(height)]
另一方面,如果你真的想“优化”,那么你可能想在C语言中重新实现这个算法,并使用SWIG之类的语言从python中调用它。干涉模式很有趣,不是吗 所以,首先,这将是次要的,因为在我的笔记本电脑上运行这个程序只需要12.5秒 但是让我们看看通过numpy数组操作执行第一位可以做些什么,好吗?我们基本上有您想要的:
arr[i][j] = abs(hypot(i-s1x,j-s1y) - hypot(i-s2x,j-s2y))
对于所有i
和j
因此,既然numpy有一个hypot
函数可以在numpy数组上工作,那么我们就使用它。我们的第一个挑战是获得一个大小合适的数组,每个元素都等于i
,另一个数组的每个元素都等于j
。但这并不难;事实上,下面的一个答案指向了我以前不知道的奇妙的numpy.mgrid
,它就是这样做的:
array_i,array_j = np.mgrid[0:width,0:height]
将(宽度,高度)
大小的数组设置为(宽度,高度,3)
以与图像生成语句兼容是一件小事,但这很容易做到:
arr = (arr * np.ones((3,1,1))).transpose(1,2,0)
然后,我们将其插入到您的程序中,并通过数组操作完成操作:
import math, array
import numpy as np
from PIL import Image
size = (800,800)
width, height = size
s1x = width * 1./8
s1y = height * 1./8
s2x = width * 7./8
s2y = height * 7./8
r,g,b = (255,255,255)
array_i,array_j = np.mgrid[0:width,0:height]
arr = np.abs(np.hypot(array_i-s1x, array_j-s1y) -
np.hypot(array_i-s2x, array_j-s2y))
arr = (arr * np.ones((3,1,1))).transpose(1,2,0)
arr2 = np.zeros((width,height,3),dtype="uint8")
for ld in [200,116,100,84,68,52,36,20,8,4,2]:
print 'now computing image for ld = '+str(ld)
# Rest as before
新的时间是。。。8.2秒。所以你可以节省整整四秒钟。另一方面,这几乎完全是在图像生成阶段,所以也许你可以通过只生成你想要的图像来收紧它们。如果你使用数组操作而不是循环,速度会快得多。对我来说,图像生成现在需要很长时间。我没有使用两个
i,j
循环,而是:
I,J = np.mgrid[0:width,0:height]
D1 = np.hypot(I - s1x, J - s1y)
D2 = np.hypot(I - s2x, J - s2y)
arr = np.abs(D1-D2)
# triplicate into 3 layers
arr = np.array((arr, arr, arr)).transpose(1,2,0)
# .. continue program
您希望在未来记住的基本点是:这是关于优化的而不是;在numpy中使用数组形式只是像应该使用的那样使用它。根据经验,您未来的项目不应该绕道python循环,数组形式应该是自然形式
我们在这里做的很简单。我们找到并使用了
numpy.hypot
而不是math.hypot
。像所有这样的numpy函数一样,它接受ndarray作为参数,并且做我们想要的事情。我认为您应该深入了解问题的细节。在算法中寻找优化比较容易。如果您只发布代码,我们必须阅读代码,从代码中找出算法,然后尝试优化它。因此,发布您的原始问题和解决方案,而不是一堆代码。您可以用arr=(arr*np.ones((3,1,1)))替换您称为“笨拙”的行。转置(1,2,0)
谢谢。不过,这种倍增似乎代价高昂。我现在意识到可能np.array((arr,arr,arr)).transpose(1,2,0)
有效。什么是优化?这是你不应该做的事!:-)将代码放在函数中,这样在循环中使用时,hy=..
就是一个局部变量,在for循环中使用时使用快速查找。现在不相关,但它说明了愚蠢优化的本质。更好的改进是使用更好的算法(如此答案)和做更少的工作(使您的代码使用灰度,删除3个重复层)。对于列表来说,这似乎是一个足够好的改进,然而,它给了我:ValueError:形状不匹配:当我在numpy数组上尝试时,对象无法广播到单个形状,无论我如何尝试它,请参见kaizer的答案;你不能像对待Python数据结构那样对待NumPy对象。好吧,看来你的答案和盖伊·贝娄(guy bellow)的计时器都缩短了30秒(是的,我有一台蹩脚的pc,但图像保存部分对我来说也是10秒),虽然我不确定接受谁的答案,我会支持你的,因为你似乎在我的答案上投入了更多的精力,做了完全相同的事情。不过,您必须重视解释,这就是为什么我们在这里讨论stackoverflow,做得很好。和@LWolf,你应该投票给你接受的答案,因为你觉得它很有用。我明白了:-)欢迎来到stackoverflow!
I,J = np.mgrid[0:width,0:height]
D1 = np.hypot(I - s1x, J - s1y)
D2 = np.hypot(I - s2x, J - s2y)
arr = np.abs(D1-D2)
# triplicate into 3 layers
arr = np.array((arr, arr, arr)).transpose(1,2,0)
# .. continue program