将scipy RectBivariateSpline的调用并行化

4

我正在编写一个Python代码,需要在任意一组点上多次求解2D样条曲线。代码如下:

spline = scipy.interpolate.RectBivariateSpline(...)
for i in range(1000000):
    x_points, y_points = data.get_output_points(i)
    vals = spline.ev(x_points, y_points)
    """ do stuff with vals """

没有输出点的重叠。由于"data.get_output_points"使用了大量内存, 我希望使用线程或某种共享内存来并行化此过程。开始时,我尝试启动10个线程,每个线程处理循环的1/10。然而,这不会比单线程运行更快。
通过对代码进行性能分析,发现其时间全部花费在 "fitpack2.py:674(\__call__)" 中,即 "_BivariateSplineBase" 评估函数中。这似乎是由于GIL问题导致的,因此线程无法独立运行。
如何解决GIL问题并实现并行化?有没有一种调用“fitpack”例程的方法可以良好地并行化,或者我可以使用其他样条曲线?我的输入网格是均匀超采样的,但输出点可以位于任何位置。 我已经尝试过使用“RegularGridInterpolator”(线性插值),其性能足够好,但使用线程并行化效果不佳。
编辑:下面是我所谓的纯线程并行化。
def worker(start, end):
    for i in range(start, end):
        x_points, y_points = data.get_output_points(i)
        vals = spline.ev(x_points, y_points)
        """ do stuff with vals """

t1 = threading.Thread(target=worker, args=(0, 500000)).start()
t2 = threading.Thread(target=worker, args=(500001, 1000000)).start()
t1.join()
t2.join()

你可以展示一下你是如何将那段代码并行化的吗? - ali_m
当然,我添加了一个例子。我只是将for循环在不同的线程之间分割。 - Kyle
1个回答

1

是的,你说得对。我进一步研究了这个问题,dfitpack代码从未禁用GIL,因此无法使用线程实现我所希望的功能。我不确定为什么在进入Fortran代码时它会保留GIL,但可能只是因为没有人花时间弄清楚什么可以禁用GIL,什么不能。我将重新构建所有内容以使用多进程。 - Kyle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接