Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Channel Element type too large Golang

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.

like image 216
benjano Avatar asked May 24 '17 12:05

benjano


People also ask

What is channel type in Golang?

In Golang, or Go, channels are a means through which different goroutines communicate. Think of them as pipes through which you can connect with different concurrent goroutines. The communication is bidirectional by default, meaning that you can send and receive values from the same channel.

Are Go channels blocking?

Channel operation (i.e. write or read) are blocking in nature. This means: When we send data into the channel using a GoRoutine, it will be blocked until the data is consumed by another GoRoutine. When we receive data from channel using a GoRoutine, it will be blocked until the data is available in the channel.

Are Go channels FIFO?

Channels make goroutines share memory by communicating. We can view a channel as an internal FIFO (first in, first out) queue within a program. Some goroutines send values to the queue (the channel) and some other goroutines receive values from the queue.

What are the differences between unbuffered and buffered channels?

When a channel is created with no capacity, it is called an unbuffered channel. In turn, a channel created with capacity is called a buffered channel. To understand what the synchronization behavior will be for any goroutine interacting with a channel, we need to know the type and state of the channel.


1 Answers

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.)

like image 184
icza Avatar answered Sep 22 '22 08:09

icza