我正在尝试加速我的python脚本,它使用vtk
方法(和vtkobjects
)来处理几何测量。由于我的一些方法包括循环非常相似的网格并为每个网格计算封闭点,我只是想将这种for循环并行化:
averaged_contained_points = []
for intersection_actor in intersection_actors:
contained_points = vtk_mesh.points_inside_mesh(point_data=point_data, mesh=intersection_actor.GetMapper().GetInput())
mean_pos = np.mean(contained_points, axis=0)
averaged_contained_points.append(mean_pos)
在这种情况下,函数vtk_mesh.points_inside_mesh
会调用vtk.vtkSelectEnclosedPoints()
并将vtkActor
和vtkPolyData
作为输入。
主要问题是:如何将其转换为并行运行?
我最初的尝试是import multiprocessing
,但后来切换到import pathos.multiprocessing
,这似乎有一些优点,但它们的工作方式非常相似。
问题是以下代码不起作用。
def _parallel_generate_intersection_avg(inputs):
point_data = inputs[0]
intersection_actor = inputs[1]
contained_points = vtk_mesh.points_inside_mesh(point_data=point_data, mesh=intersection_actor.GetMapper().GetInput())
if len(contained_points) is 0:
return np.array([-1,-1,-1])
return np.mean(contained_points, axis=0)
pool = ProcessingPool(CPU_COUNT)
inputs = [[point_data,intersection_actor] for intersection_actor in intersection_actors]
averaged_contained_points = pool.map(_parallel_generate_intersection_avg, inputs)
导致这类错误:
pickle.PicklingError: Can't pickle 'vtkobject' object: (vtkPolyData)0x111ed5bf0
我做了一些研究,发现vtkobjects可能无法腌制:
Can't pickle <type 'instancemethod'> when using python's multiprocessing Pool.map()
但是,由于我找不到与可用答案并行运行python vtk代码的解决方案,如果您有任何建议,请告诉我。
[编辑]
我没有尝试实现线程,主要是因为我在这个帖子中读到了对答案的评论:How do I parallelize a simple Python loop?
在CPython上使用多个线程不会给你带来更好的性能 因全局解释器锁(GIL)而导致的纯Python代码
答案 0 :(得分:2)
与线程不同,将参数传递给多处理进程 参数必须能够使用pickle进行序列化。
示例:
def functionWithPickableInput(inputstring0):
r0 = vtk.vtkPolyDataReader()
r0.ReadFromInputStringOn()
r0.SetInputString(inputstring0 )
r0.Update()
polydata0 = r0.GetOutput()
return functionWithVtkInput(polydata0)
#compute the strings to use as input (they are the content of the correspondent vtk file)
vtkstrings = []
w = vtk.vtkPolyDataWriter()
w.WriteToOutputStringOn()
for mesh in meshes:
w.SetInputData(mesh)
w.Update()
w.WriteToOutputStringOn()
vtkstrings.append(w.GetOutputString())
在这里,我选择在内存中编写所有内容(请参阅http://www.vtk.org/doc/nightly/html/classvtkDataReader.html#a122da63792e83f8eabc612c2929117c3,http://www.vtk.org/doc/nightly/html/classvtkDataWriter.html#a8972eec261faddc3e8f68b86a1180c71中的方法)。 当然,您必须在并行循环之外调用编写器,因此您必须判断编写器的开销是否与您要并行化的函数相关。您还可以从文件中读取您的polydata, 如果你有ram问题。