Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 在Python程序中设计并发性_Multithreading_Python 3.x_Concurrency_Python Multithreading - Fatal编程技术网

Multithreading 在Python程序中设计并发性

Multithreading 在Python程序中设计并发性,multithreading,python-3.x,concurrency,python-multithreading,Multithreading,Python 3.x,Concurrency,Python Multithreading,我正在设计一个大型项目,我想我看到了一种方法,可以通过利用多核来大幅提高性能。然而,我在多处理方面没有任何经验,我有点担心我的想法可能不是好的 创意 该程序是一款视频游戏,程序性地生成大量内容。由于一次生成的内容太多,因此程序会尝试在需要之前生成所需内容,并花费大量精力来预测在不久的将来需要什么以及该未来有多近。因此,整个程序是围绕任务调度器构建的,任务调度器获取传递的函数对象,并附加一些元数据,以帮助确定它们应该按什么顺序处理,并按该顺序调用它们 动机 似乎应该很容易让这些函数在它们自己的进程

我正在设计一个大型项目,我想我看到了一种方法,可以通过利用多核来大幅提高性能。然而,我在多处理方面没有任何经验,我有点担心我的想法可能不是好的

创意

该程序是一款视频游戏,程序性地生成大量内容。由于一次生成的内容太多,因此程序会尝试在需要之前生成所需内容,并花费大量精力来预测在不久的将来需要什么以及该未来有多近。因此,整个程序是围绕任务调度器构建的,任务调度器获取传递的函数对象,并附加一些元数据,以帮助确定它们应该按什么顺序处理,并按该顺序调用它们

动机

似乎应该很容易让这些函数在它们自己的进程中并发执行。但是查看多处理模块的文档让我重新考虑——似乎没有任何简单的方法在线程之间共享大型数据结构。我忍不住想象这是故意的

问题

因此,我想我需要知道答案的基本问题是:

  • 是否有任何实用的方法允许多个线程访问同一个列表/目录/等等。。。同时阅读和写作?我可以启动我的星型生成器的多个实例,让它访问包含所有星型的dict,并让新对象从其他线程的角度出现在dict中吗(也就是说,我不必明确地从制作它的过程中获取星星;我只需将它从dict中拉出,就好像主线程将它自己放在那里一样)

  • 如果没有,是否有任何实用的方法允许多个线程同时读取相同的数据结构,但将其生成的数据反馈给主线程,以便安全地滚动到相同的数据结构中

  • 即使我确保没有两个并发函数试图同时访问相同的数据结构(无论是读还是写),这种设计是否可行

  • 数据结构是否可以在进程之间固有地共享,或者我是否总是像在TCP流上通信的进程那样,显式地从一个进程向另一个进程发送数据?我知道有一些对象会抽象掉这类东西,但我想问的是,是否可以完全去掉它;让对象在每个线程中都有看的其实是同一块内存

  • 模块提供的用于抽象进程间通信的对象有多灵活?我可以使用它们作为现有代码中使用的数据结构的替代品,而不注意任何差异吗?如果我这样做,会导致无法管理的开销吗

  • 对不起,我太天真了,但我没有受过正规的计算机科学教育(至少,还没有)我以前从来没有使用过并发系统。我在这里尝试实现的想法是不是非常实用,或者任何允许我透明地同时执行任意函数的解决方案会导致如此多的开销,以至于我最好在一个线程中完成所有事情

    示例

    为了最大程度地说明问题,下面是一个我设想的系统工作原理示例:

    玩家已指示UI模块将视图移动到某个空间区域。它会通知内容管理模块这一点,并要求其确保玩家当前可以点击的所有星星都已完全生成并准备好点击

    内容管理模块检查并发现,用户界面所说的玩家可能尝试与之交互的几个明星实际上还没有生成单击时显示的详细信息。它生成了许多包含这些明星的方法的任务对象,这些明星在被调用时将生成必要的数据。It还向这些任务对象添加了一些元数据,假设(可能基于从UI模块收集的进一步信息)在玩家尝试单击任何东西之前,将有0.1秒的时间,并且图标最靠近光标的星星被单击的可能性最大,因此应该比远离光标的星星被请求的时间稍早。然后,它将这些对象添加到调度程序队列

    调度程序根据每个任务需要完成的时间对其队列进行快速排序,然后从队列中弹出第一个任务对象,从它包含的函数中生成一个新进程,然后不再考虑该进程,而只是从队列中弹出另一个任务并将其填充到一个进程中,然后是下一个任务,然后是下一个任务……

    同时,新进程执行,将它生成的数据存储在它所属的星型对象上,并在到达
    return
    语句时终止


    然后,UI注册玩家现在确实单击了一个星,并查找它需要在其代表性精灵被单击的星对象上显示的数据。如果数据在那里,它将显示它;如果没有,UI将显示一条消息,要求玩家等待,并继续重复尝试访问必要的属性在成功之前,对星形对象进行复制。

    即使您的问题看起来非常复杂,但有一个非常简单的解决方案。您可以隐藏使用代理在进程之间共享对象的所有复杂内容

    基本思想是创建一个管理器来管理所有应该在进程间共享的对象。然后,该管理器创建自己的进程,等待其他进程指示它更改对象
    import multiprocessing as m
    
    manager = m.Manager()
    starsdict = manager.dict()
    
    process = Process(target=yourfunction, args=(starsdict,))
    process.run()