英文:
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 // 发送复制品的地址
编辑:
声明一个全局数组就像这样简单:
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 <- &v // Sending a pointer
}()
v2 := <-a
fmt.Println(v2) // It's a pointer
fmt.Println(*v2) // It'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 <- &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.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论