Parallel Assign() 在某些设备上运行缓慢大家好,
Parallel Assign() 与某些系统结合使用似乎存在问题。
我可以使用 JMP 16.1 访问 3 台 Windows 10 PC。:
- 笔记本电脑:酷睿 i5-8350U(4 核)@ 1.9 GHz,16GB 内存
- 旧工作站:至强 E5-1660 v4(8 核)@ 3.2 GHz,256GB 内存
- 新工作站至强 W-2145(8 核)@3.7 GHz,128GB 内存
我在所有系统上使用不同的问题大小比较了我的测试脚本的并行和顺序版本的性能(下面的 scipt)。
结果出乎意料地糟糕。 只有在我的笔记本电脑上,并行版本比顺序版本稍快,但在工作站上慢了 2 倍以上。
有人在使用 Parallel Assign() 时遇到过类似的性能问题吗? 还是我用错了? 这里发生了什么?
抢


n_different_ids = 100000;
<BR />// Just generate random data. Every 15 rows must be processed at the same time.
DT_Data = J( 15*n_different_ids, 9, 0 );
For ( i = 1, i <= n_different_ids, i++,
DT_Data[15*(i-1)+(1::15),0] = i + J( 15, 9, Random Normal() );
);
<BR />// some function
F_percentile = Function( {x , p},
x = Sort Ascending(x);
n = N Rows(x);
index = 1 + (n - 1) * p;
index_ibelow = Floor(index);
index_iabove = Ceiling(index);
h = index - index_ibelow;
result = (1 - h) * x[index_ibelow] + h * x[index_iabove];
result;
);
<BR />// parallel version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
Parallel Assign( {
DT_Data = DT_Data,
F_percentile = Name Expr( F_percentile )
},
DT_Features[i,j] = (
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
result;
)
);
time_parallel = tick seconds()-start;
Show(time_parallel);
Wait(0.1);
<BR />// sequential version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
for(i=1,i<=n_different_ids,i++,
for(j=1,j<=16,j++,
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
DT_Features[i,j] =result;
);
);
time_sequential = tick seconds()-start;
Show(time_sequential);
脚本编写回复:Parallel Assign() 在某些设备上很慢这是 VirtualBox 下的 4-CPU 16GB ~3GHz 机器 JMP16/win10。 我看到了我期望的加速(不是 4 倍,但仍然不错。)
n_different_ids = 100,000;
time_parallel = 13.98333333333333;
time_sequential = 37.73333333333333;
n_different_ids = 1,000,000;
time_parallel = 141.2333333333333;
time_sequential = 375.016666666667;
并行分配是为每个 CPU 复制一个大矩阵,但在这些大小下,线性图并不表明这是一个分页问题。
观察 Windows 任务监视器的 CPU 和内存(和磁盘)使用情况,看看它是否解释了什么。 我在并行分配期间看到了 100%,在顺序测试期间看到了 25%。 我还看到在更大的并行分配期间使用了 7GB。
任务管理器
回复:Parallel Assign() 在某些设备上很慢嗨,克雷格,
我现在只是在查看我性能最差的工作站(如下)。 我在任务管理器中没有看到任何可疑的东西。 除了CPU,没有什么是接近完全占用的。
我还注意到 JMP 15.2.1 在并行和顺序版本中总是更快。 在 n=100,000 的情况下,JMP 16.1 大约需要 36s/18s(并行/顺序),而 JMP 15.2.1 31s/15s 稍微好一点,但离良好的并行性能还很远。 不幸的是,我不再有旧版本可用了。 我使用 JMP 12 编写了这段代码,当时并没有注意到性能问题(而且我使用的 PC 也不同)。
抢

回复:Parallel Assign() 在某些设备上很慢我可以在我的笔记本电脑(Win 10,JMP 16.1)上确认该行为:
time_parallel = 158.7;
time_sequential = 157.7666666666667;
n=1000000
回复:Parallel Assign() 在某些设备上很慢没有把握。 我向 JMP 发送了有关此线程的说明;您可能还想咨询技术支持。
我的猜测(仅此而已!)是 JMP 需要进行一些更改才能使性能恢复到新硬件上。 只有 4 个虚拟 CPU,我无法看到与您看到的相同的东西。
回复:Parallel Assign() 在某些设备上很慢我还在新工作站上将任务管理器中可供 JMP 使用的内核数量限制为 2、4 和 8。 并行版本仍然比顺序版本慢。 我的猜测是 JMP 在后台使用过时的库,这些库在新硬件架构上运行不佳。
谢谢 Craige,我会联系技术支持。
回复:Parallel Assign() 在某些设备上很慢对于我的 3.6GHz 4 核机器和 N=100k:
我在顺序上使用并行代码获得了 1.4 倍的加速(12.8s 并行 vs 17.8s 顺序)。 这不如 Craige 看到的 2.7 倍加速,但比您在工作站上看到的减速行为要好。 然而,我想看看我是否可以从中获得更多的性能,所以我做了一些编辑。
我通过使用表达式删除了函数调用开销(矩阵参数副本等)。 这使我获得了 2.5 倍的加速(4.5 秒并行 vs 11.3 秒顺序)并且比原始速度快了很多。 最后,我尝试重新排列循环并将顺序版本降低到 4s。 这比并行版本快,但重新排列不像并行分配那么容易。 我测试了一些不同的 N,这些模式似乎成立,但我没有像上面的表格那样进行全面扫描。 找到附上的代码。
并行:12.78
顺序:17.80
Parallel_Expr:4.50
Sequential_Expr:11.27
Sequential_Expr_Opt:3.98
回复:Parallel Assign() 在某些设备上很慢哦,哇谢谢! 在我的新工作站上运行你的脚本我得到
并行:37.0833333333139
顺序:19.7166666666453
Parallel_Expr: 6.933333333331975
Sequential_Expr:12.5333333333256
Sequential_Expr_Opt:4.54999999998836
让我们不要考虑 Sequential_Expr_Opt 一个,因为它是一种不公平的比较。 
你只是用一个表达式替换了这个函数,我得到了大约 1.5 的顺序加速和超过 5 (!!!) 的并行版本? 这是一个很好的解决方法。 那么我从中学到什么? 从不使用 JSL 中的函数? 这有点令人不快,因为函数使代码更具可读性,并且更容易和更安全地使用和修改其他人。 但是,我认为幕后的某个地方仍然存在问题,因为我的原始并行版本仍然需要原始顺序版本的两倍时间,而在 Craige 的虚拟机上并非如此。
更新:这是对新工作站的完整扫描:


回复:Parallel Assign() 在某些设备上很慢两周前,我遵循了 Craiges 的建议并联系了技术支持。 在对我的 PC 进行了一些查询之后,我今天得到了这样的答复,即开发人员已参与调查行为并修复未来 JMP 版本中的问题。
尽管如此,再次感谢 Evan 加快了这个特定脚本的速度。
回复:Parallel Assign() 在某些设备上很慢你好@罗布,两个想法:
编程速度
代码的目标会对您编写代码的方式产生重大影响。对于绝大多数脚本来说,调用函数或复制符号所需的额外时间并不重要,所以是的,您应该使用函数并使代码易于解释。另一方面,如果您正在处理一个很大的项目,并且会重复足够多的次数,以至于您关心需要多长时间,那么是的,您可能想开始用一些细节来换取原始性能。我鼓励你只花时间优化真正重要的事情。不要现在多花一个小时编写代码,然后必须多花一个小时弄清楚一年后你做了什么,因为你试图加快它变得更加复杂,只是为了每天为用户节省 20 秒的额外时间.
并行权衡
在决定是否并行执行时,您需要平衡设置“子”线程的开销与其将要执行的工作。假设您要通过打开 JMP 的另一个副本、打开数据表并单击运行来运行并行作业。 如果让它运行一个小时,那就太好了,与让一个脚本做所有事情相比,您将节省大量时间,但是如果该脚本要运行 20 秒,那么您启动它的时间可能比保存时间要多。是的,这里的开销要小得多,但复制符号和分配内存确实需要时间。确保您的脚本在环境设置后所做的工作是实质性的。您可以帮助实现这一点的一种方法是将您的循环分成 4 个部分,并让每个线程一次处理四分之一的值。因此,将您的列表分成四部分,每部分有四分之一的行,然后让您的脚本按顺序处理每个子列表。 这样您就可以将设置子线程所花费的时间从 n row() 次减少到 4 次。
回复:Parallel Assign() 在某些设备上很慢你好@ih ,
同意。
在我的情况下,设置孩子的开销并不重要,所以我没有花太多时间使这尽可能有效。 这个脚本并不意味着只运行几分钟。 在我开始这个话题之前,我完全按照你的建议做了。 我将我的数据集分成 8 个部分,并在 0.5 天内完成。 出于兴趣,我后来也尝试了 Evan 的“Sequential_Expr_Opt”版本,完成我的数据集花了 1.5 到 4 天的时间(从星期四早上开始,星期五下午没有完成,而是星期一早上)。
这个线程是为了表明一般幕后有问题。 过去,我时不时地注意到 JMP 的并行性能不佳,这让我很困扰。 我喜欢 JMP,我喜欢用它来尝试其他人说 JMP 无法完成的事情。 我很高兴开发人员正在研究它。
但是我必须说有比 JMP 更好的工具来处理非常大的数据集。 至少目前是这样。 