结果为追加到列表的多处理for循环

时间:2019-06-27 13:56:29

标签: python-3.x for-loop multiprocessing append python-xarray

我需要并行处理for循环。我当前的代码是遍历我从xarray数据集获取的id列表,从具有相应id的xarray数据集获取行数据,调用函数(计算数据的三角分布),追加函数将其转换为列表,完成后会将列表转换为xarray数据集,每个结果都链接到相应的ID,因此稍后可以在该Dataset上将该ID附加到“主要”数据集。

我的代码看起来像这样:

from sklearn.preprocessing import MinMaxScaler
import xarray as xr
import scipy.stats as st

function call_func(data):
   scaler = MinMaxScaler()
   norm_data = scaler.fit_transform(np.reshape(data, (len(data),1)))
   params = st.triang.fit(norm_data)
   arg,loc,scale = params[:-2],params[-2],params[-1]
   dist = st.triang(loc=loc, scale=scale, *arg)
   return dist

if __name__ == "__main__":
for id in my_dataset['id'].values:
        row_data= my_dataset.sel(id=id)['data'].values[0]
        if len(row_data)>3 and all(row_data== 0) == False:
                result = call_func(row_data)
                result_list.append(result)
        else:
            result_list.append([])

new_dataset = xr.Dataset({'id': my_dataset['id'].values,
                          'dist_data':(['id','dist'],
                           np.reshape(np.array(result_list),(len(result_list),1)))
                           })

由于id_array很大,因此我想使循环并行化。这是一个通用的问题,但是我是多处理工具的新手。您是否建议如何将多重处理与此任务结合在一起?我的研究非常明显地表明,多处理和附加到列表并不是最明智的选择。

1 个答案:

答案 0 :(得分:0)

我将尝试给出一个简单的虚拟示例,希望您可以推断出代码所需的修改:

这是代码的常规循环版本:

id_array = [*range(10)]

result = []
for id in id_array:
    if id % 2 == 0:
        result.append((id, id))
    else:
        result.append((id, id ** 2))

print(result)

输出:

  

[(0,0),(1,1),(2,2),(3,9),(4,4),(5,25),(6,6),(7,49 ),(8,8),(9,81)]


在这里,我使用ProcessPoolExecutor通过4个进程将其并行化:

from concurrent.futures import ProcessPoolExecutor

id_array = [*range(10)]


def myfunc(id):
    if id % 2 == 0:
        return id, id
    else:
        return id, id ** 2


result = []
with ProcessPoolExecutor(max_workers=4) as executor:
    for r in executor.map(myfunc, id_array):
        result.append(r)

print(result)

输出(相同):

  

[(0,0),(1,1),(2,2),(3,9),(4,4),(5,25),(6,6),(7,49 ),(8,8),(9,81)]


基本上:

  1. for内容提取到一个返回所需值的函数中
  2. ProcessPoolExecutorexecutor.map(myfunc, id_array)一起使用
  3. 将返回值添加到结果列表中。