通道元素类型过大 Golang

5

我正在编写一个并行处理矩阵的程序。

我的矩阵是使用常量n创建的。

const n = 10

通道是使用以下代码创建的:
a := make(chan [n][n]int)

对于小于约 12 的值的n,此方法可以正常使用。然而,如果n的值更大,则会出现以下错误:

channel element type too large (>64kB)

看了一些教程,似乎缓冲通道可能是解决这个问题的方法,但我尝试使用以下代码进行操作,结果仍然出现相同的错误:

a := make(chan [n][n]int, 1000)

我是否正确使用了缓冲通道,或者它们不是解决这个问题的方法?非常感谢您提供前进的任何提示。
编辑:根据给出的答案和评论,我现在正在尝试创建一个全局矩阵,它是空白的,go routines可以写入。
const n int = 1024

blank [n][n]int

我不确定如何在全局范围内声明它,并尝试以上方法解决此问题。它需要在全局范围内初始化吗?似乎我尝试的一切都会出现错误。

1个回答

5
频道是否缓冲与此无关,错误并不在于存储元素的空间,而在于单个元素的大小。频道元素类型的大小限制是一项实现细节/限制,您无法对其进行任何操作。
如果尝试使用违反此规则的元素类型,则表示您正在做错误的事情(您不应该这样做)。每当在通道上发送值时,该值都将被复制。因此,在通道上发送超过64KB的值并不真正有效。
相反,选择一个小的元素类型。需要最少更改的选择是使用指向您类型的指针:*[n][n]int
a := make(chan *[n][n]int)

当然,您需要在通道上发送指针,并从通道接收指针,例如:

const n = 132
a := make(chan *[n][n]int)

go func() {
    var v [n][n]int
    a <- &v // Sending a pointer
}()

v2 := <-a
fmt.Println(v2)  // It's a pointer
fmt.Println(*v2) // It's an array value

请在Go Playground上尝试。

需要注意的是,由于我们现在在通道上发送/接收指针,它将指向相同的数组值,因此修改指向的值将修改我们在通道上发送地址的同一数组。如果不想这样,请在发送之前复制并发送副本的地址:

var v [n][n]int
// Making a copy:
v2 := v
a <- &v2 // Sending address of the copy

在处理IT技术相关内容时,您应该考虑使用切片而不是数组

编辑:

声明全局数组只需这样:

var result [n][n]int

(它必须在文件范围内,而不是其他块的外部。)

嗨,感谢您的回答。我是否可以创建一个名为“matrix”的结构体,并在每次使用时使用它,而不是[n][n]int? - benjano
@benjano 这不会改变任何事情,结构体类型的大小不能小于其所有字段类型大小的总和。 - icza
如果我想要并行计算矩阵,我是否需要一个全局变量,其中包含一个相同大小的空矩阵,然后可以将其保存? - benjano
我正在生成两个随机矩阵,然后将它们相加。目前我的程序会将矩阵分成两半,并将这两个半部分传入两个不同的goroutine中进行并发处理。然后这两个半部分再被合并在一起。但由于需要在最后进行重构,因此比顺序版本要慢得多。我希望能够写入和保存到另一个矩阵中以获得结果。 - benjano
生成并添加两个小矩阵时,您可能甚至看不到性能的提升,因为同步和工作分配也有开销。话虽如此,生成和添加两个矩阵的工作可以进行拆分,而不实际拆分矩阵,因为添加矩阵只是将在相同索引处的元素相加(对于具有不同索引的元素,元素对结果没有影响)。 - icza
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接