首页 > 解决方案 > Python多处理性能不佳

问题描述

我必须使用先知对一定数量的系列(数千个)进行预测。先知工作正常,但不使用多个 CPU。每个预测大约需要 36 秒(实际上整个函数还进行了一些数据预处理和后期处理)。如果我按顺序运行(仅 15 个系列进行测试),则需要 540 秒才能完成。这是代码:

for  i in G:
    predictions = list(make_prediction(i, c, p))

其中 G 是一个迭代器,一次返回一个系列(测试上限为 15 个系列),c 和 p 是两个数据帧(函数仅使用它们来读取)。

然后我尝试使用joblib

predictions = Parallel(n_jobs=5)( delayed(make_prediction)(i, c, p) for i in G)

耗时420秒。

然后我尝试了 Pool

p = Pool(5)
predictions = list(p.imap(make_prediction2, G))
p.close()
p.join()

由于使用 map 我只能传递一个参数,因此我调用了一个调用 make_prediction(G, c,p) 的函数。耗时327秒。

最终我尝试了ray:我用 #@ray.remote 装饰了 make_prediction 并调用:

predictions = ray.get([make_prediction.remote(i, c, p) for i in G])

耗时:340秒!我还尝试使用 c_ray = ray.put(c) 制作 c 和 p ray 对象,对于 p 也一样,并将 c_ray 和 p_ray 传递给函数,但我看不到性能有任何改进。

我了解分叉所需的开销,实际上从函数中花费的时间并不多,但我希望有更好的性能(最多不到 40% 的增益,使用 5 倍的 CPU 似乎并不令人惊奇),尤其是来自 ray . 我错过了什么或做错了什么?有什么想法可以获得更好的表现吗?

让我指出,RAM 的使用是受控的。在最坏的情况下,每个进程使用不到 2GB 的内存,因此总共不到 10 个,可用的内存为 26 GB。

Mac os X 10.14.6 i7 上的 Python 3.7.7 Ray 0.8.5 joblib 0.14.1,具有 4 个物理内核和 8 个线程(cpu_count() = 8;5 cpu 工作时 pmset -g thermlog 报告没有节流)

PS 将测试规模增加到 50 系列可以提高性能,尤其是使用 ray,这意味着分叉的开销在如此小的测试中是相关的。我将进行更长的测试以获得更准确的性能指标,但我想我不会远离 50% 这个值似乎与我看到的其他帖子一致,他们使用 50 个 CPU 可以减少 90%。

**************************** 更新 ********************* **************

将要工作的系列数量增加到 100,ray并没有表现出良好的性能(也许我在它的实现中遗漏了一些东西)。Pool,相反,使用初始化函数和imap_unordered更好。分叉和准备每个流程环境都会产生明显的开销,但我得到了非常奇怪的结果:

将 CPU 数量翻倍,仅减少 12% 的时间?更糟糕的是,使用 5 个 CPU 几乎需要相同的时间(请注意,100 可以除以 1、2、4 和 5,因此队列总是被填满)!没有油门,没有交换,机器有 8 个核心,即使在运行测试时也有大量未使用的 CPU 电源,所以没有瓶颈。怎么了?

标签: pythonperformancemultiprocessingpoolray

解决方案


推荐阅读