2

这是我的问题Paralel for loop, map() works, pool.map() Gives TypeError的后续。我想做multiprocessing.Pool.map(compare_clusters, clusters_1, clusters_2),其中 compare_clusters 是一个函数, clusters_1 是对象列表, clusters_2 也是对象列表。该问题的答案清楚地表明,不像map,multiprocessing.Pool.map 只能采用一个迭代器,在这种情况下clusters_2必须是块大小。

所以我的问题是,如何用两个迭代器并行化一个循环?

编码

spectra_names, condensed_distance_matrix, index_0 = [], [], 0 
for index_1, index_2 in itertools.combinations(range(len(clusters)), 2):
    if index_0 == index_1:
        index_0 += 1
        spectra_names.append(clusters[index_1].get_names()[0])
    try:
        distance = 1/float(compare_clusters(clusters[index_1], clusters[index_2],maxiter=50))
    except:
        distance = 10
    condensed_distance_matrix.append(distance)

我如何尝试并行化它

from multiprocessing import Pool
condensed_distance_matrix, spectra_names, index_0, clusters_1, clusters_2 = [], [], 0, [], []
for index_1, index_2 in itertools.combinations(range(len(clusters)), 2):
    if index_0 == index_1:
        index_0 += 1
        spectra_names.append(clusters[index_1].get_names()[0])
    clusters_1.append(clusters[index_1])
    clusters_2.append(clusters[index_2])
pool = Pool()
condensed_distance_matrix_values = pool.map(compare_clusters, clusters_1, clusters_2)

for value in condensed_distance_matrix_values :
    try:
        distance = 1/float(value)
    except:
        distance = 10
    condensed_distance_matrix.append(distance)
4

2 回答 2

2

如果我正确理解了您的代码,那么以下应该可以工作

from multiprocessing import Pool
condensed_distance_matrix = []
spectra_names = []
index_0 = 0
cluster_pairs = []
for index_1, index_2 in itertools.combinations(range(len(clusters)), 2):
    if index_0 == index_1:
        index_0 += 1
        spectra_names.append(clusters[index_1].get_names()[0])
    cluster_pairs.append((clusters[index_1], clusters[index_2]))
pool = Pool()
condensed_distance_matrix_values = pool.map(compare_clusters, cluster_pairs)

for value in condensed_distance_matrix_values :
    try:
        distance = 1/float(value)
    except:
        distance = 10
    condensed_distance_matrix.append(distance)

因此,与其创建两个包含单个集群的列表,不如创建一个包含集群对元组的列表。新列表中的每一对都是您要比较的集群对。您可能需要compare_clusters相应地调整功能。

考虑到Blckknght的答案,您不需要遍历索引来创建一个对的列表itertools.combinations。所以你可以这样做,pool.map(compare_clusters, itertools.combinations(clusters, 2))因为组合已经返回一个元组列表。

于 2013-10-23T12:53:22.943 回答
1

在 Python 3.3 及更高版本中,您可以使用pool.starmap. 在早期版本中,您需要编写一个辅助函数:

def do_comparison(tupl):
    x, y = tupl # unpack arguments
    return compare_clusters(x, y)

pool = Pool()
values = pool.map(do_comparison, itertools.combinations(clusters, 2))
condensed_distance_matrix = [1 / float(v) if v != 0 else 10 for v in values]

我通过完全避免索引来简化了很多事情,而是直接生成集群值的 2 元组。你根本不需要你的顶部for循环。我还将反转代码简化为列表理解,而不是append每个项目调用一次的循环。

当然,您在循环中做的另一件事是提取spectra_names. 我建议不要一次做一个索引,而是使用列表理解来一次构建它(它可以与上面的池内容分开):

spectra_names = [c.get_names()[0] for c in clusters]
于 2013-10-23T12:55:03.610 回答