带线程的基本 Mapreduce 比顺序版本慢
Basic Mapreduce with threads is slower than sequential version
我正在尝试使用线程对 mapreduce 进行单词计数,但此版本比顺序版本慢得多。对于一个 300MB 的文本文件,mapreduce 版本大约需要 80 秒,而顺序版本则需要更少的时间。我的问题是因为不明白为什么,因为我已经完成了 map reduce 的所有阶段(拆分、映射、洗牌、减少),但我不知道为什么它变慢了,因为我使用了大约 6 个线程来完成测试。我在想,与执行时间相比,线程的创建可能是昂贵的,但由于它需要大约 80 秒,我认为很明显这不是问题所在。你能看一下代码看看它是什么吗?我很确定代码工作正常,问题是我不知道是什么导致了缓慢。
最后一点,当使用超过300MB的文本文件时,程序会占满我电脑的所有内存,有什么办法可以优化吗?
首先声明几个免责声明:
- 要了解应用程序运行缓慢的确切原因,您需要对其进行分析。在这个答案中,我给出了一些常识推理。
- 我假设您使用的是 cPython
当您并行化某些算法时,有几个因素会影响性能。其中一些有利于速度(我用 +
标记它们)而有些则反对(-
)。让我们看看它们:
- 你需要先拆分工作(-)
- work is parallel workers is simultaneously (+)
- 并行工作者可能需要同步他们的工作 (-)
- 减少所需时间 (-)
与顺序算法相比,为了让并行算法给您带来一些收益,您需要所有加速事情的因素超过所有拖累您的因素。
此外,与顺序处理相比,#2 的收益应该足够大以补偿您需要做的额外工作(这意味着对于某些 small
数据,您不会获得任何开销提升协调性会更大)。
现在实施中的主要问题是第 2 项和第 3 项。
首先,所有的工人都没有并行工作。您并行化的任务部分是 CPU 绑定的。在 python 中,单个进程的线程不能使用多个 CPU。所以在这个程序中它们永远不会并行执行。他们有相同的 CPU.
此外,他们对字典所做的每个修改操作都使用 locking/unlocking,这比不需要这种同步的顺序版本慢得多。
要加快您的算法,您需要:
- 使用多处理而不是多线程(这样你就可以使用多个CPU进行处理)
- 以一种不需要工人在工作时同步的方式构建算法(每个工人应该使用自己的字典来存储中间结果)
我正在尝试使用线程对 mapreduce 进行单词计数,但此版本比顺序版本慢得多。对于一个 300MB 的文本文件,mapreduce 版本大约需要 80 秒,而顺序版本则需要更少的时间。我的问题是因为不明白为什么,因为我已经完成了 map reduce 的所有阶段(拆分、映射、洗牌、减少),但我不知道为什么它变慢了,因为我使用了大约 6 个线程来完成测试。我在想,与执行时间相比,线程的创建可能是昂贵的,但由于它需要大约 80 秒,我认为很明显这不是问题所在。你能看一下代码看看它是什么吗?我很确定代码工作正常,问题是我不知道是什么导致了缓慢。 最后一点,当使用超过300MB的文本文件时,程序会占满我电脑的所有内存,有什么办法可以优化吗?
首先声明几个免责声明:
- 要了解应用程序运行缓慢的确切原因,您需要对其进行分析。在这个答案中,我给出了一些常识推理。
- 我假设您使用的是 cPython
当您并行化某些算法时,有几个因素会影响性能。其中一些有利于速度(我用 +
标记它们)而有些则反对(-
)。让我们看看它们:
- 你需要先拆分工作(-)
- work is parallel workers is simultaneously (+)
- 并行工作者可能需要同步他们的工作 (-)
- 减少所需时间 (-)
与顺序算法相比,为了让并行算法给您带来一些收益,您需要所有加速事情的因素超过所有拖累您的因素。
此外,与顺序处理相比,#2 的收益应该足够大以补偿您需要做的额外工作(这意味着对于某些 small
数据,您不会获得任何开销提升协调性会更大)。
现在实施中的主要问题是第 2 项和第 3 项。
首先,所有的工人都没有并行工作。您并行化的任务部分是 CPU 绑定的。在 python 中,单个进程的线程不能使用多个 CPU。所以在这个程序中它们永远不会并行执行。他们有相同的 CPU.
此外,他们对字典所做的每个修改操作都使用 locking/unlocking,这比不需要这种同步的顺序版本慢得多。
要加快您的算法,您需要:
- 使用多处理而不是多线程(这样你就可以使用多个CPU进行处理)
- 以一种不需要工人在工作时同步的方式构建算法(每个工人应该使用自己的字典来存储中间结果)