在python中并行化嵌套for循环以查找最大值

在python中并行化嵌套for循环以查找最大值,python,parallel-processing,multiprocessing,python-multithreading,python-multiprocessing,Python,Parallel Processing,Multiprocessing,Python Multithreading,Python Multiprocessing,我一直在努力提高这段代码的执行时间。由于计算非常耗时,我认为最好的解决方案是将代码并行化。 输出也可以存储在内存中,然后写入文件 我对Python和parallelism都是新手,因此我发现很难应用所解释的概念。我也发现了这个问题,但我无法想出如何在我的情况下实现同样的方法。 我在Windows平台上工作,使用Python 3.4 for i in range(0, len(unique_words)): max_similarity = 0 max_simila

我一直在努力提高这段代码的执行时间。由于计算非常耗时,我认为最好的解决方案是将代码并行化。 输出也可以存储在内存中,然后写入文件

我对Python和parallelism都是新手,因此我发现很难应用所解释的概念。我也发现了这个问题,但我无法想出如何在我的情况下实现同样的方法。 我在Windows平台上工作,使用Python 3.4

for i in range(0, len(unique_words)):
    max_similarity = 0        
    max_similarity_word = ""
    for j in range(0, len(unique_words)):
        if not i == j:
            similarity = calculate_similarity(global_map[unique_words[i]], global_map[unique_words[j]])
            if similarity > max_similarity:
                 max_similarity = similarity
                 max_similarity_word = unique_words[j]
    file_co_occurring.write(
        unique_words[i] + "\t" + max_similarity_word + "\t" + str(max_similarity) + "\n")
如果您需要代码的解释:

  • unique_words
    是一个单词(字符串)列表
  • global\u-map
    是一个字典,其关键字是单词(
    global\u-map.keys()
    包含与
    unique\u-words
    相同的元素),值是以下格式的字典:{word:value},其中单词是
    unique\u-words
    中值的子集
  • 对于每个单词,我根据其在
    global\u map
    中的值查找最相似的单词。我不想把每个相似性都存储在内存中,因为地图已经占用了太多的时间
  • 计算相似度
    返回0到1之间的值
  • 对于
    unique\u words
    中的每个单词,结果应该包含最相似的单词(最相似的单词应该与单词本身不同,这就是为什么我添加了条件
    if not I==j
    ,但如果我检查
    max\u similarity
    是否不同于1,也可以这样做)
  • 如果单词的
    max\u相似度
    为0,则如果最相似的单词是空字符串,则可以

    • 这里有一个适合您的解决方案。我最终改变了你的很多代码,所以如果你有任何问题,请询问

      这远远不是实现这一点的唯一方法,尤其是这不是一个内存高效的解决方案

      您需要将max_workers设置为适合您的设置。通常,计算机中逻辑处理器的数量是一个很好的起点

      from concurrent.futures import ThreadPoolExecutor, Future
      from itertools import permutations
      from collections import namedtuple, defaultdict
      
      Result = namedtuple('Result', ('value', 'word'))
      
      def new_calculate_similarity(word1, word2):
          return Result(
              calculate_similarity(global_map[word1], global_map[word2]),
              word2)
      
      with ThreadPoolExecutor(max_workers=4) as executer:
          futures = defaultdict(list)
          for word1, word2 in permutations(unique_words, r=2):
                  futures[word1].append(
                      executer.submit(new_calculate_similarity, word1, word2))
      
          for word in futures:
              # this will block until all calculations have completed for 'word'
              results = map(Future.result, futures[word])
              max_result = max(results, key=lambda r: r.value) 
              print(word, max_result.word, max_result.value, 
                  sep='\t', 
                  file=file_co_occurring)
      
      以下是我使用的库的文档:


      我认为,如果不在内存中存储一些相似性值,就无法并行运行该确切循环。你能描述一下代码的预期输出是什么吗?如果你正在寻找与集合中每个单词最相似的单词,我认为这不会这样做。是的,它应该为每个单词找到最相似的单词。它是否也应该循环内部循环中的所有单词,或者错误在其他地方?另外,如果你有一个将结果存储在内存中的解决方案,请发布它,我会找到一种方法来腾出一些空间。我认为这两个循环都有问题。外部循环跳过最后一个单词,因此您不会找到与它最相似的单词。内部循环还需要查看所有单词。例如,除非我遗漏了什么,否则在你当前的代码和单词列表[a,b,c]中,b更类似于a而不是c,你的输出将是:a最类似于b(a循环看到b),b最类似于c(b循环没有看到a,所以它选择c),而c将没有输出。你是对的。我刚刚编辑了这个问题,更好地解释了预期的输出,现在我将再次编辑它,正如您所提到的修复这个问题。谢谢。我不确定这在Python3中是否有效,但这可能值得研究:感谢提供的解决方案。我测试了一个小的输入,执行时间更糟糕。我已经读到,如果输入没有那么大,这可能是正常的,对吗?@nick,是的,对于小的输入,它可能会慢一些,因为设置线程池会有一些开销,在线程之间移动数据也会有一些开销。很难说速度是否会随着输入的增加而提高。@Nick,我忘记了gil,这可能是问题的一部分。您可以尝试ProcessPoolExecutor而不是ThreadPoolExecutor。它可能会工作,也可能不会工作。代码中有一个bug,但我真的不知道在哪里。对于完全不同的单词,它输出的相似度为1,错误肯定不在
      calculate\u similarity
      函数中,因此可能在给定给它的参数中。我尝试了一种不同的方法来解决这个问题,使用(我认为)一个更简单的并行循环,我再次陷入困境,新问题也是如此。@Nick,全局映射是在开始之前设置的,还是在运行时更新的?