对于某些线程,Python多处理循环始终停止

对于某些线程,Python多处理循环始终停止,python,multiprocessing,Python,Multiprocessing,我想通过使用多线程加速数据加载和插值。到目前为止,我的代码似乎工作正常。唯一的问题是它总是运行到给定的进程数。 假设我的档案是100份。如果我用24个内核运行脚本,只加载了24个文件,但我需要继续加载到100个。我错过了什么 print ('Number of overall VTK Files: ' + str(len(vtkArray))) def dataoperator(N,i,vtkArray,field): #for i in range(N-

我想通过使用多线程加速数据加载和插值。到目前为止,我的代码似乎工作正常。唯一的问题是它总是运行到给定的进程数。 假设我的档案是100份。如果我用24个内核运行脚本,只加载了24个文件,但我需要继续加载到100个。我错过了什么

        print ('Number of overall VTK Files: ' + str(len(vtkArray)))
    def dataoperator(N,i,vtkArray,field):
        #for i in range(N-100,N):
        print ("Loading data " +str(vtkArray[i,1] + ' index :' + str(i)))
        points, cells, point_data, cell_data, field_data = meshio.read(ID +str(vtkArray[i,1]))
        x,y,z=np.transpose(points)
        print ("\t Interpolating data " +str(vtkArray[i,1] + ' index :' + str(i)))
        from scipy.interpolate import griddata
        if (scalar=='p'):
            p = np.transpose(point_data['p'])
            pi= griddata((x, y, z), p, (xx, yy, zz), method='nearest')
            field[i,:,:,:]= pi
        else:
            u,v,w = np.transpose(point_data['subtract(U,U_bf)'])
            if (scalar=='u'):
                ui= griddata((x, y, z), u, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= ui
            elif (scalar=='v'):
                vi= griddata((x, y, z), v, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= vi
            else:
                wi = griddata((x, y, z), w, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= wi
        del points, cells, point_data, cell_data, field_data


    import multiprocessing
    jobs = []
    for i in range(0, procs):
        process = multiprocessing.Process(target=dataoperator,args=(N, i, vtkArray,field))
        jobs.append(process)

        # Start the processes 
    for j in jobs:
        j.start()

        # Ensure all of the processes have finished
    for j in jobs:
        j.join()
在您的代码中,创建了procs进程,它使用参数N、i、vtkArray和field调用dataoperator一次。索引i永远不会比进程更大

重写代码,使其使用队列:我假设vtkArray包含100个不同的案例

# Assuming python3.    
from queue import Empty as EmptyException

resultQueue = multiprocessing.Queue() # to return data from your workers
taskQueue = multiprocessing.Queue()
processes = []

def _worker(taskQueue, resultQueue, N, vtkArray, field):
    while True:
        try:
            # Block maximally 0.1s before EmptyException is thrown.
            i = taskQueue.get(timeout=0.1)
            ret = dataoperator(N, i, vtkArray, field)
            resultQueue.put(ret)
        except EmptyException:
            # Stop the loop.
            break

for i in range(len(vtkArray)):
    taskQueue.put(i)

for i in range(procs):
    process = multiprocessing.Process(target=_worker,
                                      args=(taskQueue, resultQueue, N, vtkArray, field),
                                      name="process%03d" % i)
    process.start()
    processes.append(process)

for p in processes:
    p.join()

try:
    rets = []
    while True:
        rets.append(resultQueue.get(block=False))
except EmptyException:
    pass

我没有测试这段代码,只是把它作为一个起点。我强烈建议您阅读本模块的文档。我也建议使用上下文,但这是另一回事。

由于诺曼纽斯的帮助,我能够正确设置加载和插入多个文件,此外,我仍然无法使用resultQueue.get收集数据。列表始终为空,尽管ret的_workers函数中有一个print语句给出结果:

再次澄清我的目的:

1设置一个多维数组全局定义字段=np.zeros[N,nx,ny,nz],其中N=lenvtkArray和vtkArray只是一个文件列表,最多可处理100个文件,nx,ny,nz用于插值的节点数

2 dataoperator是一个函数,用于加载和插值数据,现在使用多处理,其中索引i对应于处理器的索引,并在多维数组字段的哪一行放置加载的数据

3从normanius建议的代码似乎工作得很好,因为\u workers函数中的ret打印语句显示了正确的结果,每一个都是按流程的

4无论如何,我仍然无法使用resultQueue.get函数接收完全填充的多维数组。是否还可以再次返回多维数组,或者使用rets=[]作为列表

提前感谢您的帮助

    ###################################################
     #Loading all vtk files and saving to multidim array
    ###################################################
    def dataoperator(i,vtkArray,nx,ny,nz,x0,x1,y0,y1,z0,z1,scalar):
        xi = np.linspace(x0,x1,nx,endpoint=True)
        yi = np.linspace(y0,y1,ny,endpoint=True)
        zi = np.linspace(z0,z1,nz,endpoint=True)
        yy,xx,zz=np.meshgrid(yi,xi,zi)

        #Generate MultiDimensional array
        vtkArrayString=[str(x) for x in vtkArray[:,1]]
        print ("Loading data " +str(prefix) + str(vtkArrayString[i])+' with index ' + str(i))
        points, cells, point_data, cell_data, field_data = meshio.read('./VTK/' +str(vtkArrayString[i]))
        #points, point_data=loaddata(vtkArrayString,i)

        x,y,z=np.transpose(points)
        print ("\t Interpolating data " +str(vtkArrayString[i]))
        from scipy.interpolate import griddata
        if (scalar=='p'):
            p = np.transpose(point_data['p'])
            pi= griddata((x, y, z), p, (xx, yy, zz), method='nearest')
            field[i,:,:,:]= pi
        else:
            u,v,w = np.transpose(point_data['subtract(U,U_bf)'])
            if (scalar=='u'):
                ui= griddata((x, y, z), u, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= ui
            elif (scalar=='v'):
                vi= griddata((x, y, z), v, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= vi
            else:
                wi = griddata((x, y, z), w, (xx, yy, zz), method='nearest')
                field[i,:,:,:]= wi
        #return field, vtkArray
        print ("\t Finished Interpolating data " +str(vtkArrayString[i]))
        return field 

    import multiprocessing
    from queue import Empty as EmptyException


    resultQueue = multiprocessing.Queue() # to return data from your workers
    taskQueue = multiprocessing.Queue()
    processes = []

    def _worker(taskQueue, resultQueue, i, vtkArray):
        try:
            # Block maximally 0.1s before EmptyException is thrown.
            i = taskQueue.get(timeout=0.1)
            ret  = dataoperator(i,vtkArray,nx,ny,nz,x0,x1,y0,y1,z0,z1,scalar)
            print (ret)
            resultQueue.put(ret)
        except EmptyException:
            # Idle action, if needed.
            pass

    for i in range(steps):
        taskQueue.put(i)

    for i in range(procs):
        process = multiprocessing.Process(target=_worker,
                                          args=(taskQueue, resultQueue, i, vtkArray),
                                          name="process%03d" % i)
        process.start()
        processes.append(process)

    #ret2=np.zeros([N,nx,ny,nz])
    for p in processes:
        p.join()

    try:
        rets = []
        while True:
            rets.append(resultQueue.get(block=False))
            print (rets)
    except EmptyException:
        pass
    print(rets)
    field=np.array(rets)
    print(field)

很难判断您的问题是什么,因为您的示例并没有按照编写的方式运行。但是procs的价值是什么呢?也许这个值设置为核心数?我不是多处理方面的专家,但我认为您只为每个核心设置了一个文件。所以如果你有24个核,你只计算24个文件。您应该为每个核心设置一个文件范围,例如每个核心4或5个文件。感谢normanius的回答,我按照您的建议重新编写了代码,代码似乎正在运行,而且我无法使用resultQueue.get收集ret的结果。为了澄清,我想在下一篇帖子中提到我的目的,这是调试请求吗?我可以把工资的银行账户转帐吗请注意,我更新了我的答案,因为在所有任务被消耗之前,_worker不会在taskQueue上循环。如果无法将结果发送到主进程,则怀疑这是否会对您的问题产生影响。IIRC对于可以通过对象需要拾取的队列发送的类型对象有某些要求。您是否尝试发送字符串之类的简单对象?对我来说,代码是有效的。