并行化行为
我试图理解 Parallelize[] 行为的一些怪癖。
如果我这样做:
CloseKernels[];
LaunchKernels[1]
f[n_, g_] :=
First@AbsoluteTiming[
g[Product[Mod[i, 2], {i, 1, n/2}]
Product[Mod[i, 2], {i, n/2 + 1, n}]]];
Clear[a, b];
a = Table[f[i, Identity], {i, 100000, 1500000, 100000}];
LaunchKernels[1]
b = Table[f[i, Parallelize], {i, 100000, 1500000, 100000}];
ListLinePlot[{a, b}, PlotStyle -> {Red, Blue}]
结果就是预期的: CPU利用率:
但如果我这样做,更改要评估的函数:
CloseKernels[];
LaunchKernels[1]
f[n_, g_] :=
First@AbsoluteTiming[
g[Product[Sin@i, {i, 1, n/2}]
Product[Sin@i, {i, n/2 + 1, n}]]];
Clear[a, b];
a = Table[f[i, Identity], {i, 1000, 15000, 1000}];
LaunchKernels[1]
b = Table[f[i, Parallelize], {i, 1000, 15000, 1000}];
ListLinePlot[{a, b}, PlotStyle -> {Red, Blue}]
结果是:
CPU 利用率:
我认为我缺少一些有关 Parallelize[] 的重要知识来理解这一点。
有什么提示吗?
I'm trying to understand some quirks of the Parallelize[] behavior.
If I do:
CloseKernels[];
LaunchKernels[1]
f[n_, g_] :=
First@AbsoluteTiming[
g[Product[Mod[i, 2], {i, 1, n/2}]
Product[Mod[i, 2], {i, n/2 + 1, n}]]];
Clear[a, b];
a = Table[f[i, Identity], {i, 100000, 1500000, 100000}];
LaunchKernels[1]
b = Table[f[i, Parallelize], {i, 100000, 1500000, 100000}];
ListLinePlot[{a, b}, PlotStyle -> {Red, Blue}]
The result is the expected one:
CPU utilization:
But if I do the same, changing the function to evaluate:
CloseKernels[];
LaunchKernels[1]
f[n_, g_] :=
First@AbsoluteTiming[
g[Product[Sin@i, {i, 1, n/2}]
Product[Sin@i, {i, n/2 + 1, n}]]];
Clear[a, b];
a = Table[f[i, Identity], {i, 1000, 15000, 1000}];
LaunchKernels[1]
b = Table[f[i, Parallelize], {i, 1000, 15000, 1000}];
ListLinePlot[{a, b}, PlotStyle -> {Red, Blue}]
The result is:
CPU utilization:
I think I am missing some important knowledge about Parallelize[] to understand this.
Any hints?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的猜测是问题不在于并行化,而在于您尝试计算的内容。对于
Mod
,结果始终为 1 或 0,其乘积也是如此。对于Sin
,由于使用整数运算,因此会积累巨大的符号表达式(Sin[i]
的乘积)。它们在计算后被丢弃,但它们需要堆空间(内存分配/释放)。您观察到的二次行为可能是由于大尺寸内存分配的线性复杂性“乘以”迭代的线性复杂性所致。这似乎是主导效应,掩盖了并行化的实际成本。如果您应用N
,例如Sin@N[i]
,结果会完全不同。My guess is that the problem is not in
Parallelize
, but in what you are trying to compute. ForMod
, the result is always either 1 or 0 and the product as well. ForSin
, since you use the integer arithmetic, you accumulate huge symbolic expressions (products ofSin[i]
). They are discarded after having been computed, but they need the heap space (memory allocation/deallocation). The quadratic behavior you observe is likely due to the linear complexity of large size memory allocation, "multiplied" by the liner complexity from your iteration. This seems the dominant effect, which shadows the real costs ofParallelize
. If you applyN
, likeSin@N[i]
, the results are quite different.要了解使用 Parallelize 时幕后发生的情况,最好启用并行计算工具包的调试模式,即:
第二个示例产生大量 MathLink 通信开销,因为 Sin 函数应用于整数时,Mathematica 不会立即求值(正如 Leonid Shifrin 已经提到的那样):
以下是调试输出的一部分:
To understand what is going on behind the scenes when using
Parallelize
, it's a good idea to enable the Parallel Computing Toolkit's debugging mode, i.e.:The second example produces a lot of MathLink communication overhead, because the Sin function applied to an integer number is not immediately evaluated by Mathematica (as Leonid Shifrin already mentioned):
Here's a portion of the debugging output:
尝试一下这个版本,我相信你会知道发生了什么。
Try this version and I'm sure you will know what's going on.