Ugh, my issue was that the underlying C++ structure (held by `indicesT`)
got freed. So if I add `runtime.KeepAlive(indicesT)` to the end of the
block, things just work, as they should. The headaches of working on a
mixed GC'ed and manually managed memory environment. Correct version below:
func (l *Literal) Data() any {
if l.IsNil() {
return nil
}
rawData := unsafe.Pointer(l.cLiteralPtr.data)
len := int(l.cLiteralPtr.size)
return unsafe.Slice((int)(rawData), len)
}
...
indices = indicesT.Literal().Data().([]int)
fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
runtime.GC() // Apparently changes content of indices
fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
runtime.KeepAlive(indicesT)
...
Apologies for the noise in the list. Problem solved.
cheers
Jan
On Thursday, May 18, 2023 at 6:46:04 PM UTC+2 Jan wrote:
> hi all,
>
> I'm working on project using OpenXLA <https://github.com/openxla/xla> (c++
> library for fast execution of computation graphs) in Go, and while managing
> their implementation of "tensors" (high dimensional data) in Go, I bumped
> into an odd behavior of slices pointing to data that is managed by the C++.
>
> The full example is unfortunately too large (it would include C/C++ code),
> hopefully the relevant part I copy below is sufficient for someone to spot
> what could be happening -- I'm hoping I'm simply misunderstanding something:
>
>
> func (l *Literal) Data() any {
> if l.IsNil() {
> return nil
> }
> rawData := unsafe.Pointer(l.cLiteralPtr.data)
> len := int(l.cLiteralPtr.size)
> return unsafe.Slice((int)(rawData), len)
> }
>
> ...
> indices = indicesT.Literal().Data().([]int)
> fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
> runtime.GC() // Apparently changes content of indices
> fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
> ...
>
> The `indicesT` is generated (in C++ land) as a small vector of random
> indices, and it gets converted to a Go slice in `indices`, using
> `unsafe.Slice`.
>
> Executing the above I get something like:
>
> indices=[421 5309 10924 8068 2193 4380 3475 8713], ptr=2F66300 indices=[0
> 5309 10924 8068 2193 4380 3475 8713], ptr=2F66300
>
> Notice the value of `indices[0]` changed (!) to zero. There is no other
> goroutine that knows or interacts in any way with `indices` (or the
> underlying C++ object) -- at least that I'm aware.
>
> Curiously if I remove the call to `runtime.GC()` everything works (!).
> Took me a while to discover and isolate the issue related to garbage
> collection (it could be just correlation) since it would otherwise happen
> only very occasionally, I usually use these slices into CGO just after I
> create them.
>
> Now also very curious is that if I add a second conversion for `indices`,
> after the `fmt.Printf` (!), then the issue goes away. As in:
>
> ...
> indices = indicesT.Literal().Data().([]int)
> fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
> runtime.GC()
> fmt.Printf("\tindices=%v, ptr=%0X\n", indices, &indices[0])
> indices = indicesT.Literal().Data().([]int)
> ...
>
> A typical output now is (notice the two lines are identical, as expected):
>
> indices=[563 9434 222 8007 9770 11613 9906 11786], ptr=179C300
> indices=[563 9434 222 8007 9770 11613 9906 11786], ptr=179C300
>
> I observed the same issue with other larger tensors I was working on (some
> garbled images stored as tensors).
>
> Any thoughts ?
>
> many thanks!
> Jan
>
>
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/34c89bb8-3dd6-40f2-8da3-3bd33eba251bn%40googlegroups.com.