通道元素类型太大 Golang

huangapple go评论93阅读模式
英文:

Channel Element type too large Golang

问题

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

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

const n = 10

使用以下代码创建通道:

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

对于 n 值小于约为 12 的情况,这个方法运行良好。但是,如果 n 值更大,就会出现以下错误:

channel element type too large (>64kB)

根据教程的说明,似乎可以使用缓冲通道来解决这个问题,但是我尝试使用以下代码进行缓冲,结果仍然出现相同的错误:

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

我是否正确使用了缓冲通道?它们是否无法解决这个问题?非常感谢您对我如何解决这个问题的任何提示。

编辑:根据给出的答案和评论,我现在尝试创建一个全局矩阵,供 goroutine 写入。

const n int = 1024

var blank [n][n]int

我不确定如何在全局范围内声明它,并尝试了上述方法来解决这个问题。它是否需要在全局范围内初始化?无论我尝试什么,都会出现错误。

英文:

I'm writing a program that works with matrixes in parallel.

My matrixes are created using a constant n.

const n = 10

The channels are created with the following code:

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

This works fine for anything under a value of around 12 for n however anything greater and the following error is given:

channel element type too large (>64kB)

Looking at tutorials etc, and it seem buffered channels may be the way to solve this but I tried doing this with the following code and the same error was given:

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

Am I using buffered channels correctly or are they not the way to solve this issue? Any tips on how I can move forward with this greatly appreciated.

EDIT: Following on from the answer given and comments I'm now trying to create a global matrix which is blank and go routines can write to.

const n int = 1024

blank [n][n]int

I'm unsure how it could be declared globally and have attempted the above to solve this. Does it need initialising globally? Everything I seem to try gives errors.

答案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 // 发送一个指针
}()

v2 := <-a
fmt.Println(v2)  // 它是一个指针
fmt.Println(*v2) // 它是一个数组值

Go Playground上试一试。

你还应该记住,由于我们现在在通道上发送/接收指针,它将指向相同的数组值,因此修改指向的值将修改我们在通道上发送的相同数组的地址。如果不希望这样,发送之前先进行复制,并发送复制品的地址:

var v [n][n]int
// 进行复制:
v2 := v
a <- &v2 // 发送复制品的地址

你还应该考虑使用slices而不是arrays

编辑:

声明一个全局数组就像这样简单:

var result [n][n]int

(它必须在其他块之外,在文件范围内。)

英文:

The channel being buffered or not has nothing to do with this, the error is not with the space for storing elements but with the size of a single element. The size limit of the channel's element type is an implementation detail / restriction, you can't do anything about that.

And if you try to use an element type violating this, that signals you're doing something wrong (something you shouldn't do). Whenever you send a value on a channel, the value will be copied. So sending >64KB values on a channel is not really efficient.

Instead choose an element type which is small. The choice requiring the least change would be to use a pointer to your type: *[n][n]int.

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

Then of course you have to send pointers on the channel, and you'll receive pointers from it, e.g.:

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

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

v2 := &lt;-a
fmt.Println(v2)  // It&#39;s a pointer
fmt.Println(*v2) // It&#39;s an array value

Try it on the Go Playground.

You should also keep in mind that since now we're sending / receiving pointers on the channel, it will point to the same array value, and thus modifying the pointed value will modify the same array whose address we sent on the channel. If this is unwanted, make a copy before sending, and send the address of the copy:

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

You should also consider working with slices instead of arrays.

Edit:

Declaring a global array is as easy as this:

var result [n][n]int

(It must be outside of other blocks, in the file scope.)

huangapple
  • 本文由 发表于 2017年5月24日 20:04:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/44157929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定