簡體   English   中英

在python中並行化這個嵌套的for循環

[英]Parallelize this nested for loop in python

我正在努力改善這段代碼的執行時間。 由於計算非常耗時,我認為最好的解決方案是並行化代碼。

我是第一次使用這個問題中解釋的地圖,但后來我嘗試了一種更簡單的方法,認為我可以找到更好的解決方案。 但是我還沒有拿出任何東西,所以因為這是一個不同的問題,所以我決定把它作為一個新問題發布。

我正在使用Python 3.4在Windows平台上工作。

這是代碼:

similarity_matrix = [[0 for x in range(word_count)] for x in range(word_count)]
for i in range(0, word_count):
    for j in range(0, word_count):
        if i > j:
            similarity = calculate_similarity(t_matrix[i], t_matrix[j])
            similarity_matrix[i][j] = similarity
            similarity_matrix[j][i] = similarity

這是calculate_similarity函數:

def calculate_similarity(array_word1, array_word2):
      denominator = sum([array_word1[i] + array_word2[i] for i in range(word_count)])
      if denominator == 0:
          return 0
      numerator = sum([2 * min(array_word1[i], array_word2[i]) for i in range(word_count)])
      return numerator / denominator

以及代碼的解釋:

  • word_count是列表中存儲的唯一字的總數
  • t_matrix是一個矩陣,包含每對單詞的值
  • 輸出應該是similarity_matrix其維度為word_count x word_count還包含每對單詞的相似度值
  • 可以將兩個矩陣保存在內存中
  • 在這些計算之后,我可以很容易地找到每個單詞最相似的單詞(或者任務可能需要的前三個相似的單詞)
  • calculate_similarity采用兩個浮點列表,每個浮點列表用於一個單獨的單詞(每個都是t_matrix中的一行)

我使用一個13k字的列表,如果我正確計算了我的系統上的執行時間將是幾天。 所以,任何能在一天內完成工作的事情都會很精彩!

也許只有在calculate_similarity中對numeratordenominatorcalculate_similarity才會有顯着的改進。

這是與Matt的答案相同的通用算​​法的替代實現,只是使用multiprocessing.Pool而不是concurrent.futures.ProcessPoolExecutor 它可能比他的代碼更有效,因為輸入( t_matrix )的值只被序列化一次並傳遞給每個工作進程中的initializer函數。

import multiprocessing
import itertools

def worker_init(matrix):
    global worker_matrix
    worker_matrix = matrix

def worker(i, j):
    similarity = calculate_similarity(worker_matrix[i], worker_matrix[j])
    return i, j, similarity

def main(matrix):
    size = len(matrix)
    result = [[0]*size for _ in range(size)]
    with multiprocessing.Pool(initializer=worker_init, initargs=(matrix,)) as pool:
        for i, j, val in pool.starmap(worker, itertools.combinations(range(size), 2)):
            result[i][j] = result[j][i] = val
    return result

if __name__ == "__main__":
    # get t_matrix from somewhere
    main(t_matrix)
from concurrent.futures import ProcessPoolExecutor, Future, wait
from itertools import combinations
from functools import partial

similarity_matrix = [[0]*word_count for _ in range(word_count)]

def callback(i, j, future):
    similarity_matrix[i][j] = future.result()
    similarity_matrix[j][i] = future.result()

with ProcessPoolExecutor(max_workers=4) as executer:
    fs = []
    for i, j in combinations(range(wordcount), 2):
        future = excuter.submit(
                    calculate_similarity, 
                    t_matrix[i], 
                    t_matrix[j])

        future.add_done_callback(partial(callback, i, j))
        fs.append(future)

    wait(fs)

對於如此大量的數據,您正在使用許多列表推導。 我強烈推薦numpy模塊。 如果這是一個選項,你可以這樣做:

import numpy as np
import itertools

t = np.array(t_matrix)

s = np.sum(t,axis=1)

denom = s[:,None] + s[None,:]
num = np.zeros((word_count,word_count))

for i,j in itertools.product(range(word_count),repeat=2):
    num[i,j] = np.where(t[i] <= t[j], t[i], t[j]).sum()

similarity_matrix = np.where(denom != 0.0, 2.*num/denom, 0 )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM