GO在并发时使用math/rand包时遇到的坑

linkwwj · · 88 次点击 · · 开始浏览    

起因

最近在用go写一个raytracing光线追踪器,光线追踪针对每一个光线进行跟踪并计算最终结果,且每个光线之间互不干扰,非常适合利用并行计算进行计算时间的优化。

问题

然而当我将计算并行化之后却发现并行计算的时间居然远远超出单线程的计算时间,十分怪异。一开始认为是开启太多goroutine导致调度负载过高而拖慢计算,排查后发现显然不是。
遂利用go自带的pprof工具采集cpu信息进行分析,发现sync.(*Mutex).lockSlow消耗了大量的时间,在排除了本身程序架构上的锁问题之后,那么,是什么导致如此长时间的锁消耗呢?

解决

经过研究,最终发现问题出在使用的rand.Float64()函数上。math/rand包中的函数默认使用了一个全局锁,在并发加高频率调用的情况下,全局锁损耗非常大。
解决方法也比较简单,对每个并发的goroutine,单独生成一个rand就行了。

source := rand.NewSource(time.Now().UnixNano())
generator := rand.New(source)

参考:https://stackoverflow.com/questions/14298523/why-does-adding-concurrency-slow-down-this-golang-code?newreg=5d8bcde4a3cd4cf8b2d95fbdfb1f2d7e


欢迎关注我们的微信公众号,每天学习Go知识

本文来自:简书

感谢作者:linkwwj

查看原文:GO在并发时使用math/rand包时遇到的坑

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:muxilin131420 备注:入群;或加QQ群:815126783

88 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传