多处理一次计算多个文本文件中的频率

Multiprocessing to count frequency in multiple text files at once

我有 2 个文本文件。我想在他们两个中找到一个字母(例如:“L”)的频率。有没有办法应用 ThreadPoolExecutor 或 ProcessPoolExecutor 来加快速度?

到目前为止我试过它只会增加花费的时间。

def countFreq(data):
    res = {i : data.count(i) for i in set(data)}
    print(res)

这是我正在使用的频率计数功能。我也将文本文件转换为字符串。

#Normal method    
start = time.time()

countFreq(str1)
countFreq(str2)
end = time.time()

print(f"Time taken: {end-start:.5f} seconds\n")

上面的代码比下面的代码快,这是为什么

#Method multiprocessing
start = time.time()

p1 = multiprocessing.Process(countFreq(str1))
p2 = multiprocessing.Process(countFreq(str2))

p1.start()
p2.start()
p1.join()
p2.join()

end = time.time()
print(f"Time taken: {end-start:.5f} seconds\n")

关于如何运行它们更快的任何想法?是IO相关还是处理相关的问题?

使用 parallel/concurrent 编程不一定会提高程序的 速度 ,有时最好按顺序保持它,特别是如果我们期望从这些 threads/processes 要做的是计算文本文件中的每个字母。

创建一个新进程需要大量资源并使用您的 CPU(s) 以便 运行 它们并行。与使用线程执行相同操作相比,生成和管理进程需要大量的计算时间和能力,但即使这样也不能保证。

为了仅计算 2 个文件,我会尝试 threads/keep 按顺序进行。当文件数量变大时,我们基本上会注意到顺序和并行加速之间的差异。

有关更多信息,我强烈建议阅读有关 Amdahl's law 的内容。

作为旁注,您应该将函数地址传递给 multiprocessing.Process 内的 target 参数,并将参数传递给 args 参数。请注意,它应该是 Tuple[Any] 类型,因此您应该添加一个尾随逗号:target=countFreq, args=(str1,)

import time
import multiprocessing


def count_freq(data):
    res = {i: data.count(i) for i in set(data)}
    print(res)


def text_to_string(path):
    with open(path, 'r') as file_handler:
        return file_handler.read()


def main():
    start = time.time()

    count_freq(text_to_string('./text1'))
    count_freq(text_to_string('./text2'))
    # about 0.001
    end = time.time()

    print(f'sequential: {end - start} s')

    start = time.time()

    p1 = multiprocessing.Process(target=count_freq, args=(text_to_string('./text1'),))
    p2 = multiprocessing.Process(target=count_freq, args=(text_to_string('./text2'),))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    end = time.time()

    print(f'concurrent: {end - start} s')


if __name__ == '__main__':
    main()