Go的隐秘世界:从 Cgo 到 Goroutine 调度

王益 · · 879 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

我曾经以为 Go 程序能调用 C 函数是天经地义的,就像 C++ 程序可以调用 C。

我也曾经以为 C 函数在 goroutine 里的执行,就如同 Go 函数被 goroutine 执行一样,没有什么差别。

这些幻想在开发 GoTorch github.com/wangkuiyi/go 的过程里彻底破灭了。

作为一个深度学习库,GoTorch 调用 PyTorch 的 C++ 内核 libtorch —— 即使 GoTorch 不依赖 libtorch,也得依赖 TensorFlow 的 C++ 内核,因为深度学习的基本操作,在 TensorFlow 里被称为 operators 的,或者在 PyTorch 里被称为 native functions,都是用 C++ 写的 —— 所以 GoTorch 离不开 Cgo。

在 GoTorch 的开发过程中,我们发现,即使一个 GoTorch 程序只用一个 goroutine 来做训练,也会”无缘无故“地启动非常多的操作系统线程,从而占用相当大的内存。

为了解决这个问题,我们一路寻找线索,不知不觉就深入到了 Cgo 以及它和 goroutine 调度机制之间的关系。这个探索过程,带我们进入到一个大多数 Go 程序员并不了解的隐秘世界。

这个寻求答案的探索过程从 Googling 开始。有一些非常值得一读的文章,比如 William Kennedy 的 Scheduling In Go 三部曲。如其开篇所说:

The design and behavior of the Go scheduler allows your multithreaded Go programs to be more efficient and performant. This is thanks to the mechanical sympathies the Go scheduler has for the operating system (OS) scheduler. However, if the design and behavior of your multithreaded Go software is not mechanically sympathetic with how the schedulers work, none of this will matter.
Go 调度器让大家可以高效地开发高性能的多线程程序。这归功于 Go 调度器和操作系统调度器的和谐。然而,如果我们的应用程序设计不能和 Go 调度器保持这种和谐,那么上述优势都成了泡影。

其实,如果我们的程序不调用 system calls 或者 C/C++ 库,只是纯粹的 Go 程序的话,还真不容易打破这种和谐。但是一旦涉及类似高性能计算,不管是基于 CPU、GPU、还是 TPU 的,那么势必要调用底层库,要通过Cgo;而使用 Cgo 很容易打破这种和谐。

为了保持和谐,我们必须了解这个隐秘世界。这远不是读完这些 Google 出来的文章就足够了的。我们不得不深入Go 编译器和 runtime 的源码。这一系列文章记述我们探寻 Go 的隐秘世界的过程。

如果你准备好了,那就开始吧!

王益:Go的隐秘世界:有Thread为啥还要Goroutinezhuanlan.zhihu.com图标


有疑问加站长微信联系(非本文作者)

本文来自:知乎专栏

感谢作者:王益

查看原文:Go的隐秘世界:从 Cgo 到 Goroutine 调度

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

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