LWo*_*olf 2 python optimization for-loop physics numpy
好吧,我最近有这个功课(不用担心,我已经完成了它,但在c ++中)但我很好奇我怎么能在python中做到这一点.问题是关于发光的2个光源.我不会详细介绍.
这是代码(我在后一部分设法优化了一点):
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)
arr = np.zeros((width,height,3))
hy = math.hypot
print 'computing distances (%s by %s)'%size,
for i in xrange(width):
if i%(width/10)==0:
print i,
if i%20==0:
print '.',
for j in xrange(height):
d1 = hy(i-s1x,j-s1y)
d2 = hy(i-s2x,j-s2y)
arr[i][j] = abs(d1-d2)
print ''
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)
arr2 *= 0
arr2 += abs(arr%ld-ld/2)*(r,g,b)/(ld/2)
print 'saving image...'
ar2img = Image.fromarray(arr2)
ar2img.save('ld'+str(ld).rjust(4,'0')+'.png')
print 'saved as ld'+str(ld).rjust(4,'0')+'.png'
Run Code Online (Sandbox Code Playgroud)
我已经设法优化了大部分内容,但是在2 for-s的部分中仍然存在巨大的性能差距,我似乎无法想到使用常见阵列操作绕过它的方法......我是接受建议:D
编辑:回应弗拉德的建议,我将发布问题的细节:有2个光源,每个发光作为正弦波:E1 = E0*sin(omega1*时间+ phi01)E2 = E0*sin(omega2*时间+ phi02)我们认为omega1 = omega2 = omega = 2*PI/T和phi01 = phi02 = phi0为简单起见,将x1视为距离平面上一个点的第一个源的距离,即光的强度点是Ep1 = E0*sin(ω*时间 - 2*PI*x1/lambda + phi0)其中lambda =光速*T(振荡周期)考虑到平面上的两个光源,公式变为Ep = 2*E0*cos(PI*(x2-x1)/ lambda)sin(欧米茄时间-PI*(x2-x1)/ lambda + phi0)从中我们可以看出,当(x2-)光的强度最大时x1)/ lambda =(2*k)*PI/2和最小值当(x2-x1)/ lambda =(2*k + 1)*PI/2并且在它们之间变化,其中k是整数
对于给定的时刻,给定光源的坐标,以及已知的λ和E0,我们必须制作一个程序来绘制光看起来如何我认为我尽可能地优化了问题. ..
干扰模式很有趣,不是吗?
所以,首先这将是次要的,因为在我的笔记本电脑上按原样运行这个程序只需要12秒半.
但是,让我们看看通过numpy数组操作做第一位可以做些什么呢,不是吗?我们基本上你想要:
arr[i][j] = abs(hypot(i-s1x,j-s1y) - hypot(i-s2x,j-s2y))
Run Code Online (Sandbox Code Playgroud)
为了所有i和j.
因此,由于numpy具有hypot适用于numpy数组的函数,所以让我们使用它.我们的第一个挑战是获得一个正确大小的数组,每个元素等于,i而另一个元素等于j.但这并不太难; 事实上,下面的答案指出了我numpy.mgrid之前我不知道的精彩内容:
array_i,array_j = np.mgrid[0:width,0:height]
Run Code Online (Sandbox Code Playgroud)
将(width, height)-sized数组放入(width,height,3)与图像生成语句兼容的细微问题,但这很容易做到:
arr = (arr * np.ones((3,1,1))).transpose(1,2,0)
Run Code Online (Sandbox Code Playgroud)
然后我们将它插入到您的程序中,让事情通过数组操作完成:
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
Run Code Online (Sandbox Code Playgroud)
而新的时间是...... 8.2秒.所以你可以节省四秒钟.另一方面,现在几乎只在图像生成阶段,所以也许你可以通过生成你想要的图像来收紧它们.