公告:1)网站程序升级:Q2A升级到1.8.6,Wordpress升级到5.7.2
2)修复了头像加载慢与提交问题反应慢等问题
2021-06-16

欢迎来到 Mathematica 问答社区

提问时请贴上文本代码

语法高亮:在编辑器中点击

被禁止的话题:广告破解

请阅读:《提问的智慧》

备用域名:mma.ooo

支持LaTex数学公式
行内公式标识符:\$ 或“$\backslash ($”+“$\backslash )$”,
行间公式标识符:\$\$ 或 “$\backslash [$”+“$\backslash ]$”

社区建议QQ群:365716997

分类

0 投票
1.6k 浏览

形如ProgressIndicator和Monitor并不能显示Parallel系列的计算过程。

但是Parallel系列的函数都可以在分配内核之后分解成ParallelEvaluate[expr,{ker1,ker2,...}]的形式,能不能设计代码分别地监控各个并行核的进度来监控整个计算的进度?

 

ps:已有前提:需要计算的函数的计算量已经充分大到,无论如何分配计算到各个并行内核,均不足以在短时间内完成计算。

=================================================================

debug:

Clear["Global`*"]
CloseKernels[];
KernelNum = 2;
LaunchKernels[KernelNum];
Proc = ConstantArray[0., KernelNum];
SetSharedVariable[Proc];
fn := Cos[i];
eachKernel[id_] := Module[{}, Proc[[Mod[id, 2] + 1]] += 1;
  {Hue[(Arg[fn] + \[Pi])/(2 \[Pi]), 1/(1 + 0.3 Log[Abs[fn] + 1]), 
    1 - 1/(1.1 + 5 Log[Abs[fn] + 1]), 1], i}]
Column@Table[With[{m = m}, Dynamic[Proc[[m]]]], {m, 1, KernelNum}]
ParallelTable[eachKernel[i], {i, -20, 20, 0.1}]

报错:

分类:动态交互 | 用户: EmberEdison (806 分)
重新分类 用户:EmberEdison

2 个回答

+1 投票
Clear["Global`*"]
CloseKernels[];
KernelNum = 2;
LaunchKernels[KernelNum];
Proc = ConstantArray[0., KernelNum];
SetSharedVariable[Proc];
eachKernel[id_] := Module[{},
  Proc[[Mod[id, 2] + 1]] += 1;
  Sum[i,{i,1000000}]
  ]
Column@Table[With[{m = m}, Dynamic[Proc[[m]]]], {m, 1, KernelNum}]
ParallelTable[eachKernel[i], {i, 20}];

如果并行计算的东西属于0.00001秒然后计算次数100000次这类,那么会极大影响整体运行时间。

串行版本是:

f[id_] := Module[{}, Sum[i, {i, 1000000}]]
Table[f[i], {i, 20}]

 

用户: 苹果 (2.2k 分)
修改于 用户:苹果
这个程序的串行版本是咋样的?我每次运行最后一行都会有很大几率得到不同的结果。
现在算是看明白了...最少 12 个字符
对于非整值和符号值报错...出错过程已附加
仔细看程序.程序中用id对每个proc进行进度+1,但是你的id设置成了浮点数,所以不存在proc的第1.1部分.
你还需要理解一下我的程序的思路.首先在主内核中申明一个进度变量,并共享到各子内核中,并在主内核中用dynamic实时更新该进度变量.随后,我们只需要在子内核的运算中,不断改变该共享变量即可.由于我是从其他地方复制粘贴再修改的程序,所以设置了proc是两个数,分别对应2个内核,用mod和part来确定修改哪个proc.你完全可以修改为proc只有一个数,所有子内核共同修改此数,因此不涉及到part.
0 投票
(*不建议核函数计算较快(<0.1s)的使用本程序。感谢@苹果*)



RebootLaunchKernels[n___] := (
   CloseKernels[];
   LaunchKernels[n];);
bootParallelMonitor[n___] := (
   (*清除旧定义*)
   UnsetShared[$Proc];
   Clear[$Proc];
   (*判定是否需要重启内核*)
   If[$KernelCount < 2,
    RebootLaunchKernels[n],
    If[IntegerQ[n] \[And] (n =!= $KernelCount), 
     RebootLaunchKernels[n], Null],
    RebootLaunchKernels[n]];
   (*建立并行计算监视器*)
   $Proc = ConstantArray[0., $KernelCount + 1];
   SetSharedVariable[$Proc];
   Column@
    Table[With[{m = m}, Dynamic[$Proc[[m]]]], {m, 
      1, $KernelCount + 1}]);
$KernelMonitor[id_] := Module[{},(*分类累加器*)If[IntegerQ[id] \[And] (id > 1),
    $Proc[[Mod[id, $KernelCount] + 1]] += 1, Null];
   (*主累加器*)
   $Proc[[$KernelCount + 1 + 0*id]] += 1;
   (*被并行执行的核函数*)
   $Parallelfn];

运行示例:

bootParallelMonitor[]
fn := Cos[i];
$Parallelfn =
  Hue[(Arg[fn] + \[Pi])/(2 \[Pi]), 1/(1 + 0.3 Log[Abs[fn] + 1]), 
   1 - 1/(1.1 + 5 Log[Abs[fn] + 1]), 1];
ParallelTable[$KernelMonitor[i], {i, -20, 20 ,0.1}, Method -> "CoarsestGrained"]

测速:

$Parallelfn = Sum[i, {i, 1000000}];
getData[n_] := 
  AbsoluteTiming[
      Short[ParallelTable[#[i], {i, n}]]] & /@ {$KernelMonitor} // 
   Flatten;
getData1[n_] := 
  AbsoluteTiming[
      Short[ParallelTable[#[i], {i, n}]]] & /@ {$Parallelfn} // 
   Flatten;

TableForm[getData1 /@ {30, 50, 130, 200, 2000, 10000}, 
 TableHeadings -> {{"n=30", "n=50", "n=130", "n=200", "n=2000", 
    "n=10000"}, {"t2", "Parallel"}}]
TableForm[getData /@ {30, 50, 130, 200, 2000, 10000}, 
 TableHeadings -> {{"n=30", "n=50", "n=130", "n=200", "n=2000", 
    "n=10000"}, {"t1", "ParallelMonitor"}}]

结果是挺令人懵逼的。我正在考虑找另外的途径来实现这个目的,而不是用动态更新。。

 

用户: EmberEdison (806 分)
这个和动态更新无关。凑12字符。
...