python - 多处理 Python 库中的慢速数据结构

标签 python process multiprocessing

我正在尝试使用多处理库对大型数据结构进行简单计算。这是我论文需要的东西,所以请不要对我严厉。

当我决定为多个“worker”、“threads”、“processes”划分我的计算或根据需要调用它时,我开始研究 python 文档以找到我需要的东西,我找到了两个模块,“threading”和“多处理”。阅读后,我决定使用“多处理”,因为它看起来像我需要的东西。

问题是,如果有多个工作人员(进程),我的计算速度会慢得多。首先想到的是我输入数据的大小。我知道对于小数据,运行线程的“成本”比简单的计算要大得多,但对于更大的结构,效率应该提高。

对于迭代算法,我的计算(例如 2D Rosenbrock)比使用少数进程进行的计算快几倍,这让我感到非常惊讶。计算是针对 100k 元组完成的。

我还注意到 multiprocessing.Queue 访问比访问 collections.deque 慢几倍,但我真的需要这种计算是某种“共享内存”或类似的东西。

谁能告诉我问题出在哪里?难道 Python 如此高效以至于不值得用多进程计算它吗?我是否使用了正确的数据结构?我可以改变我对多处理的看法吗?或者甚至我用不好的方式衡量它?我非常感谢任何可以加快速度的线索。

完整代码如下

#!/usr/bin/python
import multiprocessing
from timeit import default_timer as timer
import random
import collections

class Worker(multiprocessing.Process):
    counter = 0
    def __init__(self, idx, from_queue):
        super(Worker, self).__init__()
        self.from_queue = from_queue
        self.idx = idx

    def run(self):
        print ("Worker started", self.idx)
        for data in iter(self.from_queue.pop, None):
            x_1, x_2 = data
            result = 100*(x_2-x_1**2)**2 + (1-x_1)**2

def main():
    tuple_counts = 100000
    min_x = -5
    max_x = 5

    tuples = multiprocessing.Queue()
    for _ in range(tuple_counts):
        my_tuple = {random.uniform(min_x, max_x), random.uniform(min_x, max_x)}
    tuples.put(my_tuple)

    cores = multiprocessing.cpu_count() - 1

    pops = []
    for _ in range(cores):
        pop = collections.deque()
        pops.append(pop)

    for pop in pops:
        for _ in range(int(tuple_counts/cores)):
            pop.append(tuples.get())


    for _ in range(int(tuple_counts % cores)):
        pops[_].append(tuples.get())

    for pop in pops:
        pop.append(None)

    workers = []
    process_time = 0
    process_time_start = timer()
    for i in range(multiprocessing.cpu_count()-1):
        worker = Worker(i, pops[i])
        workers.append(worker)
        worker.start()
    for worker in workers:
        worker.join()
    process_time_stop = timer()
    process_time += (process_time_stop-process_time_start)
    print("process_time", process_time)

    iter_time = 0
    iter_timer_start = timer()
    for _ in range(tuples.qsize()):
        x_1, x_2 = tuples.qet()
        result = 100*(x_2-x_1**2)**2 + (1-x_1)**2
    iter_timer_stop = timer()
    iter_time += (iter_timer_stop-iter_timer_start)
    print("iter_time", iter_time)

if __name__ == "__main__":
    main()

最佳答案

您正在跨进程边界传递参数以进行简单计算。我预计它会非常慢。

如果您需要速度,我建议您退回到单线程实现,并找到一种使用 numpy 对其进行矢量化的方法。使用 cProfile 对其进行分析。攻击热点。

numpy 的一个巨大好处是减少了 python 开销(名称解析、循环等)。

一旦您快速掌握了单线程方法,然后才转向并行处理。

向量化问题的另一个好处是 numpy 解锁了 GIL 以进行冗长的调用,从而允许真正的线程处理,而不是多处理。

关于python - 多处理 Python 库中的慢速数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47295824/

相关文章:

c - 流程链从最后开始彼此结束

python - Matplotlib:3D 数据的正交投影(在 2D 图中)

python - 匹配除单词以外的任何内容,正则表达式问题

python - 在 OS X 上运行的 Python 中读取/写入另一个进程内存

python - 如何在 Python 进程之间共享数据?

python - 如何使用 Python 多处理 Pool.map 在 for 循环中填充 numpy 数组

python-3.x - Python 3 多处理池

python - Verbnet : vn. classids() 返回 2 个列表,但我需要删除其中 1 个

python - 在训练数据上使用 MinMaxScaler 生成用于测试数据的 std、min 和 max

java - 如何终止进程树?