Python 试图在我的管道中应用多处理过程,但没有';我根本不工作。需要建议来解决它吗

Python 试图在我的管道中应用多处理过程,但没有';我根本不工作。需要建议来解决它吗,python,python-3.x,multiprocessing,Python,Python 3.x,Multiprocessing,我正在尝试使用多处理库来并行化下面的框架,bcoz目前,它生成的输出速度非常慢。 按照为内部循环创建新函数的多处理规则,我遵循了这个规则,但仍然没有得到输出P从不转到行功能。我不知道为什么它不调用上面的函数。 这是一个嵌套循环问题 代码如下: X_TILES = 120 Y_TILES = 69 def row(X_TILES, y, tile_SizeX_org, tile_SizeY_org, width, height, rea, stack, encoded_items_org

我正在尝试使用多处理库来并行化下面的框架,bcoz目前,它生成的输出速度非常慢。 按照为内部循环创建新函数的多处理规则,我遵循了这个规则,但仍然没有得到输出P从不转到行功能。我不知道为什么它不调用上面的函数。 这是一个嵌套循环问题

代码如下:

X_TILES = 120
Y_TILES = 69

    def row(X_TILES, y, tile_SizeX_org, tile_SizeY_org, width, height, rea, stack, encoded_items_org):
        for x in X_TILES:
            tileX_org, tileY_org, eSizeX_org, eSizeY_org = tiles_coordinates(x, y, tile_SizeX_org,tile_SizeY_org, width, height)
            t_org = img_read(rea, stack, tileX_org, tileY_org, eSizeX_org, eSizeY_org)
            encoded_items_org.append(t_org)
    
        return encoded_items_org
    
    
    def tile_size_org(tile_SizeX_org, tile_SizeY_org, width, height, rea, stack):
        nXTiles, nYTiles = num_of_tiles_to_read(width, height, tile_SizeX_org, tile_SizeY_org)
        print(nYTiles, nXTiles)
        X_TILES = range(nXTiles)
        Y_TILES = range(nYTiles)
        encoded_items_org = []
        encoded_items_or = []
        
        for y in Y_TILES:
            p = Process(target=row, args=(X_TILES, y, tile_SizeX_org, tile_SizeY_org, width, height, rea, stack, encoded_items_org))
            encoded_items_or.append(p)
            p.start()
    
        for p in encoded_items_or:
            p.join()
            return encoded_items_or
        ..................................
        ..................................
        ..................................
我正在传递p=Process(target=row,args=(X\u TILES,y,tile\u SizeX\u org,tile\u SizeY\u org,width,height,rea,stack,encoded\u items\u org))命令以在CPU内核中运行。 我很困惑我是否遵循了在python中实现多处理的正确方法。 我的笔记本电脑是12核的,所以我对这一步也很好奇:对于y/U瓷砖中的y,这个for循环是否会运行69次,因为我只有12核。 我试图将编码的每个值(它附加图像的字节)附加到列表的形式中。 请,我真的需要帮助来解决这个问题,或者一些建议会很有帮助

我不知道为什么它不调用上面的函数

这里的混乱之处在于调用了
函数,但返回值不存在。单独的进程有单独的内存,因此当子进程修改其
编码的项目组织的副本时,它不会修改主进程中的“主”副本。在子进程中运行的函数的返回值也被完全忽略,因此
返回编码的\u items\u org
没有帮助。由于没有任何内容修改
编码项目组织的“主”副本,因此它仍然是一个空列表

为了从每个子进程获得结果,必须使用由多处理模块创建的某种“共享”值,该值作为参数传递给子进程执行的函数。我经常使用
队列
在子进程和父进程之间交换项目,因为它们使用起来相对简单。
Queue
使用
Pickle
将要来回发送的项目转换为文本,因为只有文本可以在进程之间直接发送(这意味着发送的项目必须可以Pickle)

使用队列的简单示例:(请务必阅读注释)

此for循环是否将运行69次


是的,循环将运行
nYTiles
次,您将创建那么多子进程。大多数计算机在任何给定时间都有数百个进程在运行,这不是问题。操作系统指示cpu内核在它们之间快速切换,以便它们都能工作。更多的进程确实意味着更多的开销,超过12个并不意味着更高的速度,但它可以正常工作。每个cpu核心只使用一个进程的效率提高可能值得,也可能不值得额外的代码复杂性。

您在哪里调用
tile\u size\u org
?运行此代码时是否生成错误消息?一种可能的调试方法是尝试在循环之外创建、启动和加入流程,并确保它在那里工作。还有一个潜在问题是
函数的返回值。子进程实际上不会返回任何内容,因此
encoded\u items\u org
将始终为空。您必须使用a才能访问父进程中的
encoded\u items\u org
。@Czaporka,在此之后,如果name==“main”:zstack=0 tile\u size\u org(tile\u SizeX\u org,tile\u SizeY\u org,width,height,reader,zstack)@RohinDasari,我想你已经理解了我的问题,是的,你的组织总是空的。我浏览了一个共享值链接,但我不明白我应该在行函数中传递什么样的值。还有一件事,我没有收到任何错误,它正在运行,但在我检查CPU历史记录时没有使用CPU(我可以确定,它什么也没做,只是在内存中加载了每个进程,但它从未调用或操作行函数)。@YubrajGupta而一些事情,如
多处理.Pool
为您做,为了从子进程中获取任何数据,必须使用某种共享值<代码>返回编码的\u项目\u组织
行的末尾()。每个子进程都有自己的独立副本,因此每个
encoded\u items\u org
都是一个单独的列表(在进程结束时被丢弃)。我倾向于经常使用
队列
,因为它通常很容易使用,并且很容易理解正在发生的事情(尽管它的效率不是很高)。或者,如果您真的想使用多处理,可以使用
多处理.Pool
进行迭代。这将允许您设置要使用的工作人员数量,这可能有助于管理您的CPU资源。这个/multiprocessing.html(简介)中的第一个例子向您展示了如何使用它。@Aaron,谢谢您的评论。我明白你上面写的。我尝试了您的上述建议,但q.put(encoded_items_org)没有附加12个列表值中的encoded_items_org=[](我不知道为什么)。我没有得到任何错误。它打开process.py并转到_bootstrap并卡在util._exit_function()。有时它只运行所有进程,但编码的项目组织是空的。@Aaron,下面是完整的代码:如果没有访问特定系统的权限,这将很难调试。可以解决线程死锁问题的简单添加是
多处理。设置启动方法(“spawn”)
。不过,这已经是Windows和MacOS的默认设置,因此它可能会非常有用,也可能不会非常有用。我的下一个想法是,
reader
可能不能
pickle
-able。可能在子pr中重新创建读取器一次
def row(q, X_TILES, y, tile_SizeX_org, tile_SizeY_org, width, height, rea, stack):
    encoded_items_org = [] #always starts empty in each child anyway, so don't bother passing it as an argument
    for x in X_TILES:
        tileX_org, tileY_org, eSizeX_org, eSizeY_org = tiles_coordinates(x, y, tile_SizeX_org,tile_SizeY_org, width, height)
        t_org = img_read(rea, stack, tileX_org, tileY_org, eSizeX_org, eSizeY_org)
        encoded_items_org.append(t_org)

    q.put(encoded_items_org) #put to shared queue so it isn't thrown away after the process finishes


def tile_size_org(tile_SizeX_org, tile_SizeY_org, width, height, rea, stack):
    nXTiles, nYTiles = num_of_tiles_to_read(width, height, tile_SizeX_org, tile_SizeY_org)
    print(nYTiles, nXTiles)
    X_TILES = range(nXTiles)
    Y_TILES = range(nYTiles)
    encoded_items_org = []
    encoded_items_or = []
    
    q = multiprocessing.Queue() #create a queue to pass to the child processes as an argument
    
    for y in Y_TILES:
        p = Process(target=row, args=(q, X_TILES, y, tile_SizeX_org, tile_SizeY_org, width, height, rea, stack))
        encoded_items_or.append(p)
        p.start()
        
    for _ in Y_TILES: #this only works if each process puts exactly one item to the queue. otherwise you must track how many times to call "get" some other way.
        encoded_items_org += q.get() #you must "get" all items from the queue before the child processes are "join"ed
        
    for p in encoded_items_or:
        p.join()

    return encoded_items_or #this line was previously inside the for loop when it probably shouldn't be. 

if __name__ == "__main__": #make sure you always use this with multiprocessing to actually start your processes
    tile_size_org(...)