并行代码比串行代码慢(值函数迭代示例)
Posted
技术标签:
【中文标题】并行代码比串行代码慢(值函数迭代示例)【英文标题】:Parallel code slower than serial code (value function iteration example) 【发布时间】:2016-02-29 19:12:21 【问题描述】:我正在尝试使用并行化使 Julia 中的代码更快。我的代码嵌套了串行 for 循环并执行值函数迭代。 (如http://www.parallelecon.com/vfi/中所述)
以下链接显示了我编写的代码的串行和并行版本: https://github.com/minsuc/MyProject/blob/master/VFI_parallel.ipynb(也可以在github页面找到DefinitionPara.jl中定义的函数。)串行代码定义为main(),并行代码定义为main_paral()。
main() 中的第三个 for 循环是我找到给定的最大化器的步骤(nCapital,nProductivity)。正如官方并行文档中所建议的那样,我将工作分布在 nCapital 网格上,该网格由许多点组成。
当我为串行和并行代码执行@time 时,我得到了
序列:0.001041 秒
并行:0.004515 秒
我的问题如下:
1) 我添加了两个工人,每个工人的工作时间分别为 0.000714 秒和 0.000640 秒,正如您在 ipython 笔记本中看到的那样。并行代码较慢的原因是开销成本?
2)我通过改变增加了网格点的数量
vGridCapital = collect(0.5*capitalSteadyState:0.000001:1.5*capitalSteadyState)
即使每个工作人员完成大量工作,串行代码也比并行代码快得多。当我添加更多工人时,串行代码仍然更快。我认为有问题,但我一直无法弄清楚......这是否与我在并行化函数中传递太多参数的事实有关
final_shared(mValueFunctionNew, mPolicyFunction, pparams, vGridCapital, mOutput, expectedValueFunction)?
非常感谢您的 cmets 和建议!
【问题讨论】:
也可能存在硬件限制,如果您只有一个处理器,您的并行代码实际上仍在以额外开销串行运行。 我有四个核心(8 个逻辑工作者)。我怀疑使用 SharedArray 会使代码比串行代码慢。会不会是这样? 【参考方案1】:如果同步之间的工作量非常小,则任务同步开销可能太长。请记住,常见的 OS 时间片时间片是 10 毫秒,而您在 1 毫秒范围内进行测量,因此在稍微负载的情况下,让所有工作线程同步的 4 毫秒延迟是完全合理的。
在所有任务访问同一个共享数据结构的情况下,访问锁定开销很可能是罪魁祸首,如果共享数据结构是线程安全的,即使是更长的并行任务。
在某些情况下,可以对输入和输出使用非线程安全的共享数组,但必须确保工作人员不会破坏彼此的结果。
取决于工作线程到底在做什么,例如,如果它们输出到相同的数组元素,可能需要为每个工作线程提供自己的输出数组,并最终将它们合并在一起,但这并不你的任务似乎不是这样。
【讨论】:
感谢您的回答!另外,关于你的回答,我想再问你一件事。在我的示例中,每个工作人员都输出到相同的数组元素。 (到名为 ValueFunctionNew 的 SharedArray)所以我想给每个工作人员“自己的输出数组”,并按照你的描述将它们合并到最后。你能给我一个简单的例子或参考吗? 据我所见,输出到mValueFunctionNew[nCapital, nProductivity]
,这是同一个数组,但您似乎可以通过nProductivity
并行化,每个nProductivity
都有一个工作人员,如果我正确地解释了您代码的内部工作原理。在这种情况下,您只需对mValueFunctionNew
进行切片,然后将子数组放在最后。
我使用 nCapital 维度而不是 nProductivity 进行了并行化,因为 nCapital 维度由大量点组成。这就是final_shared(...)
函数在main_paral()
代码中所做的事情。 (您可以在 github.com/minsuc/MyProject/blob/master/DefinitionPara.jl 中看到 final_shared(...) 的样子)。我使用 SharedArray 以便每个进程的工作都可以保存在mValueFunctionNew
中。我不太明白你所说的子数组是什么意思...
子数组我的意思是有nProductivity
一维mValueFunctionNew
数组,并在最后将它们连接成一个二维数组。以上是关于并行代码比串行代码慢(值函数迭代示例)的主要内容,如果未能解决你的问题,请参考以下文章
为啥我使用 openMP atomic 的并行代码比串行代码花费更长的时间?