7

Go 的口号是“不要通过共享内存进行通信;而是通过通信来共享内存”。我想知道 Go 是使用共享内存还是分布式计算方法。例如,对于 MPI,它显然是分布式的,OpenMP 显然是共享内存;但我不确定 Go 是独一无二的。

我看过很多帖子,例如Shared memory vs. Go channel communication,有效的 Go 文档等,但无法澄清。提前致谢。

4

2 回答 2

15

Go 不会阻止您在 goroutines/线程之间共享内存。他们所说的通信的意思是,您通过通道发送数据块或指向该块的指针。这有效地将数据的“所有权”转移给了通道的目标阅读器。请注意,这种所有权转移不是由语言或运行时强制执行的,它只是按照惯例。

如果你愿意的话,你仍然完全有能力从两个 goroutine 写入相同的内存。换句话说:Go 不会阻止你在脚下开枪,它只是提供了语言语义,使这些错误更容易被发现。

如果一个值被传递到一个通道,程序员必须假设该值不再是他在同一个 goroutine 中写入的。

func F(c chan *T) {
    // Create/load some data.
    data := getSomeData()

    // Send data into the channel.
    c <- data

    // 'data' should now be considered out-of-bounds for the remainder of
    // this function. This is purely by convention, and is not enforced
    // anywhere. For example, the following is still valid Go code, but will
    // lead to problems.
    data.Field = 123
}
于 2012-12-15T22:30:56.517 回答
5

该问题假设共享内存和分布式计算是相反的。这有点像问:RAM 和 LAN 是对立的吗?区分 CPU/内存节点内的共享内存并发和 CPU/内存节点之间的共享内存并发会更清楚。

这是并行处理研究大局的一部分。有许多研究项目,包括:

  • 开发具有多个 CPU 共享单个内存的非冯诺依曼计算机,并通过某种形式的交换结构(通常是 Clos 网络)加入。OpenMP 非常适合这些。

  • 开发由一组 CPU 组成的并行计算机,每个 CPU 都有自己独立的内存,并且在节点之间有一些通信结构。这通常是 MPI 的所在地。

第一个案例专门针对高性能计算兄弟会。我们大多数人都熟悉后一种情况。在这种情况下,这些天通信通常只是通过以太网,但是已经(成功地)为某些特定领域开发了各种更快的低延迟替代方案(例如, IEEE1355 SpaceWire,它来自 Transputer 串行链路)。

多年来,主流观点是只有在共享内存的情况下才能实现有效的并行性,因为(天真地)假设通过传递消息进行通信的成本是令人望而却步的。对于共享内存并发,困难在于软件:因为一切都是相互依赖的,所以随着系统变得越来越大,设计并发变得越来越难。需要核心专业知识。

对于我们其他人来说,Go 遵循 Erlang、Limbo,当然还有 Occam,以促进消息传递作为编排要完成的工作的手段。这源于通信顺序过程的代数,它为创建任何规模的并行系统提供了基础。CSP 设计是可组合的:每个子系统本身都可以是更大系统的一个组件,没有理论上的限制。

您的问题提到了 OpenMP(共享内存)和 MPI(分布式内存消息传递),它们可以一起使用。Go 可以被认为与 MPI 大致等效,因为它促进了消息传递。然而,它也允许锁和共享内存。Go 与 MPI 和 OpenMP 都不同,因为它没有明确关注多处理器系统。要进入使用 Go 进行并行处理的世界,需要一个网络消息传递框架,例如OpenCL,有人正在为此开发 Go API。

于 2012-12-16T13:52:28.677 回答