【问题标题】:Using multiprocessing in a class在类中使用多处理
【发布时间】:2014-08-19 11:21:40
【问题描述】:

我在混乱的代码配置中完美地使用了multiprocessing。我决定对我的代码进行一些排序并将其重写为一个类,然后我可以轻松更改输入,我的新代码如下:

class LikelihoodTest:
      def __init__(self,Xgal,Ygal):
          self.x=Xgal
          self.y=Ygal
          self.objPosition=gal_pos
          self.beta_s=beta
          self.RhoCrit_SigmaC=rho_c_over_sigma_c
          self.AngularDiameter=DA
          self.RhoCrit=rho_crit
          self.Reducedshear=observed_g
          self.ShearError=g_err
      #The 2D function
      def like2d(self,posx, posy):
          stuff=[self.objPosition, self.beta_s, self.RhoCrit_SigmaC , self.AngularDiameter, self.RhoCrit]
          m=4.447e14
          c=7.16
          param=[posx, posy, m, c]
          return reduced_shear( param, stuff, self.Reducedshear, self.ShearError)
      def ShearLikelihood(self):
          n=len(self.x)
          m=len(self.y)
          shared_array_base = multiprocessing.Array(ctypes.c_double, n*m)
          shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
          shared_array = shared_array.reshape( n,m)
          #Restructure the function before you create instance of Pool.
          # Parallel processing
          def my_func(self,i, def_param=shared_array):
              shared_array[i,:] = np.array([float(self.like2d(self.x[j],self.y[i])) for j in range(len(self.x))])
          while True:
                try:
                   print "processing to estimate likelihood in 2D grids......!!!"
                   start = time.time()
                   pool = multiprocessing.Pool(processes=10)
                   pool.map(my_func, range(len(self.y)))
                   print shared_array
                   end = time.time()
                   print "process time:\n",end - start
                   pool.close()
                except ValueError:
                   print "Oops! value error!"
          return shared_array
      def plotLikelihood(self,shared_array):
          #plotting on a mesh the likelihood function in order to see whether you have defined the inputs correctly and you can observe the maximum likelihood in 2D
          # Set up a regular grid of interpolation points
          xi, yi = np.linspace(self.x.min(), self.x.max(), 100), np.linspace(self.y.min(), self.y.max(), 100)
          # Interpolate
          rbf = scipy.interpolate.interp2d(self.x, self.y,shared_array , kind='linear')
          zi = rbf(xi, yi)
          fig, ax = plt.subplots()
          divider = make_axes_locatable(ax)
          im = ax.imshow(zi, vmin=shared_array.min(), vmax=shared_array.max(), origin='lower',
                        extent=[self.x.min(), self.x.max(), self.y.min(),self.y.max()])
          ax.set_xlabel(r"$Xpos$")
          ax.set_ylabel(r"$Ypos$")
          ax.xaxis.set_label_position('top')
          ax.xaxis.set_tick_params(labeltop='on')
          cax = divider.append_axes("right", size="5%", pad=0.05)
          cbar = fig.colorbar(im,cax=cax, ticks=list(np.linspace(shared_array.max(), shared_array.min(),20)),format='$%.2f$')
          cbar.ax.tick_params(labelsize=8) 
          plt.savefig('/users/Desktop/MassRecons/Likelihood2d_XY_Without_Shear_Uncertainty.pdf', transparent=True, bbox_inches='tight', pad_inches=0)
          plt.close()

当我尝试使用类配置运行它时出现以下错误:

if __name__ == '__main__':
     Xgal = np.linspace(Xgalaxy.min(), Xgalaxy.max(), 1000)
     Ygal = np.linspace(Ygalaxy.min(), Ygalaxy.max(), 1000)          
     Test=LikelihoodTest(Xgal,Ygal) 
     Test.ShearLikelihood()
processing to estimate likelihood in 2D grids......!!!
ERROR: PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed [multiprocessing.pool]
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 34, in ShearLikelihood
  File "/vol/1/anaconda/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/vol/1/anaconda/lib/python2.7/multiprocessing/pool.py", line 558, in get
    raise self._value
cPickle.PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

有办法解决吗?

【问题讨论】:

  • 是的。在模块级别或作为实例方法定义my_func。 Python 对于它可以腌制和不能腌制的内容非常有限,并且它不会腌制嵌套函数。
  • @JoelCornett 我在哪里可以定义shared_array,因为它是my_func 的输入并且是局部变量?
  • 好吧,首先,您可以将它作为tuple 参数的一部分传递(即zip() 它到range())。顺便说一句,我不明白为什么你需要将所有东西都包装在一个类中。另外,我不确定您是否打算将您的 pool.map 调用包装在 while 循环中?
  • @JoelCornett 因为它是两个循环,除了这种方式我不知道应该怎么做,虽然没有必要我可以删除它。但是我需要一个类的结构!

标签: python class multiprocessing pickle


【解决方案1】:

我终于可以弄清楚如何在课堂上使用multiprocessing。我使用pathos.multiprocessing 并更改代码如下:

import numpy as np
import pathos.multiprocessing as multiprocessing 

class LikelihoodTest:
      def __init__(self,Xgal,Ygal):
          self.x=Xgal
          self.y=Ygal
          self.objPosition=gal_pos
          self.beta_s=beta
          self.RhoCrit_SigmaC=rho_c_over_sigma_c
          self.AngularDiameter=DA
          self.RhoCrit=rho_crit
          self.Reducedshear=observed_g
          self.ShearError=g_err
          #The 2D function
      def like2d(self,posx, posy):
          stuff=[self.objPosition, self.beta_s, self.RhoCrit_SigmaC , self.AngularDiameter, self.RhoCrit]
          m=4.447e14
          c=7.16
          param=[posx, posy, m, c]
          return reduced_shear( param, stuff, self.Reducedshear, self.ShearError)
      def ShearLikelihood(self,r):
          return [float(self.like2d(self.x[j],r)) for j in range(len(self.x))]
      def run(self):
          try:
              print "processing to estimate likelihood in 2D grids......!!!"
              start = time.time()
              pool = multiprocessing.Pool(processes=10)
              seq=[ self.y[i] for i in range( self.y.shape[0])]
              results=np.array( pool.map(self.ShearLikelihood, seq ))
              end = time.time()
              print "process time:\n",end - start
              pool.close()
          except ValueError:
              print "Oops! value error ....!"
          return results
      def plotLikelihood(self,shared_array):
          #plotting on a mesh the likelihood function in order to see whether you have defined the inputs correctly and you can observe the maximum likelihood in 2D
          # Set up a regular grid of interpolation points
          xi, yi = np.linspace(self.x.min(), self.x.max(), 100), np.linspace(self.y.min(), self.y.max(), 100)
          # Interpolate
          rbf = scipy.interpolate.interp2d(self.x, self.y,shared_array , kind='linear')
          zi = rbf(xi, yi)
          fig, ax = plt.subplots()
          divider = make_axes_locatable(ax)
          im = ax.imshow(zi, vmin=shared_array.min(), vmax=shared_array.max(), origin='lower',
                        extent=[self.x.min(), self.x.max(), self.y.min(),self.y.max()])
          ax.set_xlabel(r"$Xpos$")
          ax.set_ylabel(r"$Ypos$")
          ax.xaxis.set_label_position('top')
          ax.xaxis.set_tick_params(labeltop='on')
          cax = divider.append_axes("right", size="5%", pad=0.05)
          cbar = fig.colorbar(im,cax=cax, ticks=list(np.linspace(shared_array.max(), shared_array.min(),20)),format='$%.2f$')
          cbar.ax.tick_params(labelsize=8) 
          plt.savefig('/users/Desktop/MassRecons/Likelihood2d_XY_coordinate.pdf', transparent=True, bbox_inches='tight', pad_inches=0)
          plt.close()

if __name__ == '__main__':
     Xgal = np.linspace(Xgalaxy.min(), Xgalaxy.max(), 1000)
     Ygal = np.linspace(Ygalaxy.min(), Ygalaxy.max(), 1000)          
     Test=LikelihoodTest(Xgal,Ygal) 
     x=Test.run()
     Test.plotLikelihood(x)

现在它就像一个魅力! :)

【讨论】:

  • 之所以有效,是因为pathos.multiprocessing 使用了更强大的序列化程序。
  • @MikeMcKerns 你知道我为什么收到this error message
  • 您的代码无法运行,如上所示。你还没有定义所有的全局变量。
  • @MikeMcKerns 答案代码确实有效,甚至我也得到了情节,但令人惊讶的是它也引发了错误消息。
  • 对,但我的意思是,我不能像上面那样复制粘贴和运行你的代码。
【解决方案2】:

您不能使用 Pickle 将函数或方法传递给不同的进程,但可以传递字符串。

您可以维护一个方法字典并通过它们的字符串键引用方法。这不是很优雅,但解决了问题。

编辑: 当您使用多处理时,有一个隐含的“分叉”。这会创建多个没有共享资源的独立进程,因为这样,您传递给另一个进程的每一件事都必须使用 Pickle 进行序列化。问题是pickle不允许序列化可执行代码以将其发送到另一个进程。

【讨论】:

  • 你的回答对我来说有点含糊。在此之前,我将like2d 传递给多处理,它可以完美地工作,而不是一个类的方法。
  • 当你使用多处理时,有一个隐含的“fork”。这会创建多个没有共享资源的独立进程,因为这样,您传递给另一个进程的每一件事都必须使用 Pickle 进行序列化。问题是pickle不允许序列化可执行代码以将其发送到另一个进程。
  • 严格来说并非如此。请参阅 this answerthis answer 以及 python docs on pickling
猜你喜欢
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-27
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多