如何使用Python多处理摆脱嵌套的while循环

如何使用Python多处理摆脱嵌套的while循环,python,multithreading,python-2.7,Python,Multithreading,Python 2.7,我做了这个光线跟踪器来模拟两个镜头。每次光线击中屏幕时,屏幕上的位置都会被投票。然而,这运行得太慢了。这与光线跟踪器无关,只是光线的绝对数量(128^4)。我知道多线程技术对此不起作用,但我如何使用多线程技术来为屏幕上的像素投票呢。这让我很困惑——我如何让每个孩子为一个像素投票。每条光线都是独立的。下面是一些示例代码。创建输入数据也有一个问题。仅仅制作一个射线数组来发送给一个多处理类需要很长时间 基本上,我希望内部循环产生多达8个子进程-让这些子进程投票-然后释放一个插槽…我认为即使这样也会运行

我做了这个光线跟踪器来模拟两个镜头。每次光线击中屏幕时,屏幕上的位置都会被投票。然而,这运行得太慢了。这与光线跟踪器无关,只是光线的绝对数量(128^4)。我知道多线程技术对此不起作用,但我如何使用多线程技术来为屏幕上的像素投票呢。这让我很困惑——我如何让每个孩子为一个像素投票。每条光线都是独立的。下面是一些示例代码。创建输入数据也有一个问题。仅仅制作一个射线数组来发送给一个多处理类需要很长时间

基本上,我希望内部循环产生多达8个子进程-让这些子进程投票-然后释放一个插槽…我认为即使这样也会运行缓慢

import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
from matplotlib.mlab import griddata
from matplotlib import cm
import random

A = 0
B = 0
C = 0
D = 0
E_initial = np.zeros((512,512))

while A <= 50:
    B = 0
    while B <= 50:
        C = 0
        while C <= 50:
            D = 0
            while D <= 50:
                #Ray tracing here             
                x_contact = random.randint(0,511)
                y_contact = random.randint(0,511)               
                E_initial[x_contact,y_contact] += 1
                D = D + 1
            C = C +1
        B = B + 1
    print A
    A = A + 1
fig = plt.figure()
ax = fig.add_subplot(111)
plt.imshow(E_initial)
cbar = plt.colorbar(orientation='vertical')
cbar.set_label('# of contacts', rotation=270, labelpad=10)
plt.show()
将numpy导入为np
从mpl_toolkits.mplot3d导入Axes3D
从matplotlib导入cm
从matplotlib.ticker导入LinearLocator,FormatStrFormatter
将matplotlib.pyplot作为plt导入
从matplotlib.mlab导入网格数据
从matplotlib导入cm
随机输入
A=0
B=0
C=0
D=0
E_initial=np.零((512512))

在尝试多重处理之前,请注意,可以消除四重while循环 通过利用一些numpy函数

indices = np.random.randint(0, 512**2, size=(50**4))
生成介于0(包含)和512**2(独占)之间的随机索引位置。 每个索引位置对应于
E_initial
中的一个位置

然后可以使用
np.bincount
计算每个索引位置出现的次数。
np.bincount
返回的数组大小为512**2,每个位置都包含一个整数计数,对应于索引位置在
索引中出现的次数。但是啊哈——这就是我们想要的
E_initial
相等

import numpy as np
import matplotlib.pyplot as plt

indices = np.random.randint(0, 512**2, size=(50**4))
E_initial = np.bincount(indices).reshape((512, 512))

fig = plt.figure()
ax = fig.add_subplot(111)
plt.imshow(E_initial)
cbar = plt.colorbar(orientation='vertical')
cbar.set_label('# of contacts', rotation=270, labelpad=10)
plt.show()

另外,让8个进程修改一个数组会很慢,因为在分配过程中必须锁定数组,以避免竞争条件导致错误结果。必须锁定每个赋值将使多进程代码比等效的单进程代码慢得多

PPS。虽然

E_initial[x_contact,y_contact] += 1

这是一些语言(如C)的标准实践,在Python中使用NumPy数组时速度非常慢。它的速度很慢,因为每个赋值至少涉及三个Python函数调用(
\uuuu getitem\uuuuu
\uuuuu iadd\uuuu
\uuu setitem\uuuu
)。如果你把它放在四重循环中,你会得到(至少)3*50**4个Python函数调用。如果您可以将所有这些Python调用减少为一个NumPy函数调用,那么您的性能将得到很大提升。因此,尽可能避免将值逐个分配给NumPy数组中的各个位置!要利用NumPy,您需要最小化函数调用和循环的数量,并通过尽可能少地调用NumPy函数来最大限度地减少工作量。这通常意味着形成一个大数组,并将整个数组压缩到一个NumPy函数中,该函数用C或Fortran进行计算。

在尝试多处理之前,请注意,您可以消除四重while循环 通过利用一些numpy函数

indices = np.random.randint(0, 512**2, size=(50**4))
生成介于0(包含)和512**2(独占)之间的随机索引位置。 每个索引位置对应于
E_initial
中的一个位置

然后可以使用
np.bincount
计算每个索引位置出现的次数。
np.bincount
返回的数组大小为512**2,每个位置都包含一个整数计数,对应于索引位置在
索引中出现的次数。但是啊哈——这就是我们想要的
E_initial
相等

import numpy as np
import matplotlib.pyplot as plt

indices = np.random.randint(0, 512**2, size=(50**4))
E_initial = np.bincount(indices).reshape((512, 512))

fig = plt.figure()
ax = fig.add_subplot(111)
plt.imshow(E_initial)
cbar = plt.colorbar(orientation='vertical')
cbar.set_label('# of contacts', rotation=270, labelpad=10)
plt.show()

另外,让8个进程修改一个数组会很慢,因为在分配过程中必须锁定数组,以避免竞争条件导致错误结果。必须锁定每个赋值将使多进程代码比等效的单进程代码慢得多

PPS。虽然

E_initial[x_contact,y_contact] += 1

这是一些语言(如C)的标准实践,在Python中使用NumPy数组时速度非常慢。它的速度很慢,因为每个赋值至少涉及三个Python函数调用(
\uuuu getitem\uuuuu
\uuuuu iadd\uuuu
\uuu setitem\uuuu
)。如果你把它放在四重循环中,你会得到(至少)3*50**4个Python函数调用。如果您可以将所有这些Python调用减少为一个NumPy函数调用,那么您的性能将得到很大提升。因此,尽可能避免将值逐个分配给NumPy数组中的各个位置!要利用NumPy,您需要最小化函数调用和循环的数量,并通过尽可能少地调用NumPy函数来最大限度地减少工作量。这通常意味着形成一个大数组,并将整个数组压缩到一个NumPy函数中,该函数用C或Fortran进行计算。

在尝试多处理之前,请注意,您可以消除四重while循环 通过利用一些numpy函数

indices = np.random.randint(0, 512**2, size=(50**4))
生成介于0(包含)和512**2(独占)之间的随机索引位置。 每个索引位置对应于
E_initial
中的一个位置

然后可以使用
np.bincount
计算每个索引位置出现的次数。
np.bincount
返回的数组大小为512**2,每个位置都包含一个整数计数,对应于索引位置在
索引中出现的次数。但是啊哈——这就是我们想要的
E_initial
相等

import numpy as np
import matplotlib.pyplot as plt

indices = np.random.randint(0, 512**2, size=(50**4))
E_initial = np.bincount(indices).reshape((512, 512))

fig = plt.figure()
ax = fig.add_subplot(111)
plt.imshow(E_initial)
cbar = plt.colorbar(orientation='vertical')
cbar.set_label('# of contacts', rotation=270, labelpad=10)
plt.show()

另外,让8个进程修改一个数组会很慢,因为在分配过程中必须锁定数组,以避免竞争条件导致错误结果。必须锁定每个赋值将使多进程代码比等效的单进程代码慢得多

PPS。虽然

E_initial[x_contact,y_contact] += 1
在某些语言中是否有标准做法