RSA加密并行计算中大量Sparks被GC回收的原因是什么?
问题分析:par/pseq并行失效与Par monad的优势
为什么par/pseq实现中大量Sparks被GC回收?
你的auxPar1实现没有真正让m1和m2并行计算,核心问题出在求值顺序和par的特性上:
par的“提示”而非强制特性:par只是向运行时发出“可以并行计算m1”的提示,但不保证一定会并行执行。当主线程后续需要m1的值时,如果对应的spark还没被工作线程调度执行,主线程会直接自行计算m1,此时这个spark就失去了存在意义,最终被GC回收。m2的同步求值逻辑:m2pseqm强制主线程先完成m2的计算,再推进到m的计算。而m依赖m1,所以主线程在算完m2后会立刻去计算m1,完全没给m1的spark留下执行时间。- 无有效并行度:整个过程中
m2完全由主线程同步计算,m1的spark也很快被主线程接管,实际并行度几乎为0,导致elapsed时间和total时间差距极小,大量spark因未被使用而被GC回收。
Par monad为什么效果更好?
auxPar4用Par monad实现的并行是显式且可靠的:
spawnP会将expmod p c dP和expmod q c dQ两个计算任务提交到Par调度器,调度器会主动将任务分配给空闲工作线程,确保两个计算任务真正并行执行。get操作会阻塞等待对应任务的结果,主线程不会提前自行计算任务内容,避免了par模式下主线程“抢任务”的问题。- 从统计结果看,elapsed时间(11.113s)远小于total时间(20.541s),说明多CPU核心被有效利用,并行效果显著。
针对par/pseq的优化建议
如果一定要用par/pseq实现正确并行,需要确保m1和m2都被作为spark提交,并且主线程在需要结果前给足并行调度时间,示例代码如下:
auxPar1Fixed :: Integer -> Integer auxPar1Fixed c = let m1 = expmod p c dP m2 = expmod q c dQ h = (qInv * (m1 - m2)) `mod` p m = m2 + h * q in m1 `par` m2 `par` (m1 `pseq` m2 `pseq` m)
这里同时将m1和m2作为spark提交,再用pseq强制主线程等待两个结果(或自行计算),能提升并行执行的概率,但这种方式仍依赖GHC运行时调度,可靠性不如Par monad。
内容的提问来源于stack exchange,提问作者Maq
相关产品推荐
相关产品推荐

