Live data from Hacker News

Gonum – Numerical Computing for Go

gonum.org

11–20 of 47 posts

Re: Gonum – Numerical Computing for Go

#11
"By default, blas64 and lapack64 call the native Go implementations of the routines. Alternatively, it is possible to use C-based implementations of the APIs through the respective cgo packages and "Use" functions."

Performance comparison? Algorithmic equivalence? How close are the results numerically (e.g. how do they compare on badly conditioned matrices)?

Re: Gonum – Numerical Computing for Go

#12
post #9

What's the use case for this? Machine learning? But data? General math use?

Here at The New York Times we are using it to power some of our recommendation algorithms. We are actually training the models with Python and serving them with Go using gonum. Our library was just open sourced (and still in my personal account, until we add more documentation): https://github.com/jbochi/facts

This sounds really cool. Anywhere I could read more about the Python -> Go integration? Or are you just exporting the raw weight matrices?

Re: Gonum – Numerical Computing for Go

#13
How does this play with Go's scheduler? My understanding is that the Go scheduler is not preemptive, and goroutines are switched out at yield point, like the start of a function body. So tight loops that don't call other functions can effectively hog the OS thread until it leaves that loop body (No idea what happens when doing FFI, maybe that's done in a separate thread pool?). For most cases where you would use Go you aren't generally doing a bunch of CPU-bound work so that doesn't matter, but here you might run into some hiccups. I'm specifically thinking of a case where you use this library to do some heavy matrix operations as part of a web service, and those tight loops hog the OS threads and hurt your bandwidth and p90 latency.

My question to the developer: is that issue something you've encountered with this library? If not, did you design the library to periodically yield in tight loops, or am I just completely wrong about the Go scheduler?

Re: Gonum – Numerical Computing for Go

#14
post #11

"By default, blas64 and lapack64 call the native Go implementations of the routines. Alternatively, it is possible to use C-based implementations of the APIs through the respective cgo packages and "Use" functions." Performance comparison? Algorithmic equivalence? How close are the results numerically (e.g. how do they compare on badly conditioned matrices)?

The algorithms are (basically) equivalent, and are translations from the Fortran (though row major instead of column major). As far as I know there are no major differences in the answers, though for extremely poorly conditioned matrices (1e14 or so) you shouldn't expect consistent answers across any implementation.

The performance story is complex. Typically we're the same speed on small matrices (and using Go is faster if you include the cgo overhead). We currently have significant speed penalties on large matrices (300x300 or so), but Kunde21 is working on assembly kernels for the BLAS functions to close that gap

Re: Gonum – Numerical Computing for Go

#15

How does this play with Go's scheduler? My understanding is that the Go scheduler is not preemptive, and goroutines are switched out at yield point, like the start of a function body. So tight loops that don't call other functions can effectively hog the OS thread until it leaves that loop body (No idea what happens when doing FFI, maybe that's done in a separate thread pool?). For most cases where you would use Go y…

I don't use Gonum with a webserver + large calculations so I can't definitively answer. No one has reported problems, but that could be a lack of usage. One thing though is that matrix multiplication (which is a kernel for higher-level operations) is written in a blocked format, and the code can be pre-empted on any of those blocks, so I wouldn't suspect it's a problem.

Re: Gonum – Numerical Computing for Go

#16
post #15

How does this play with Go's scheduler? My understanding is that the Go scheduler is not preemptive, and goroutines are switched out at yield point, like the start of a function body. So tight loops that don't call other functions can effectively hog the OS thread until it leaves that loop body (No idea what happens when doing FFI, maybe that's done in a separate thread pool?). For most cases where you would use Go y…

I don't use Gonum with a webserver + large calculations so I can't definitively answer. No one has reported problems, but that could be a lack of usage. One thing though is that matrix multiplication (which is a kernel for higher-level operations) is written in a blocked format, and the code can be pre-empted on any of those blocks, so I wouldn't suspect it's a problem.

Yeah, skimming your source it seems most of your loops involve calling some function, and even if that's inlined I believe the Go compiler will put a speculative yield call in there.

I suppose my hypothetical would be an issue if you used a non-Go BLAS implementation, as calling out to C will hog the OS thread. But this is a known issue (e.x. https://www.cockroachlabs.com/blog/the-cost-and-complexity-o...).

Re: Gonum – Numerical Computing for Go

#17
post #14
post #11

"By default, blas64 and lapack64 call the native Go implementations of the routines. Alternatively, it is possible to use C-based implementations of the APIs through the respective cgo packages and "Use" functions." Performance comparison? Algorithmic equivalence? How close are the results numerically (e.g. how do they compare on badly conditioned matrices)?

The algorithms are (basically) equivalent, and are translations from the Fortran (though row major instead of column major). As far as I know there are no major differences in the answers, though for extremely poorly conditioned matrices (1e14 or so) you shouldn't expect consistent answers across any implementation. The performance story is complex. Typically we're the same speed on small matrices (and using Go is fa…

I'm surprised your performance is anywhere near that of standard BLAS implementations. The Golang compiler doesn't have support for explicit SIMD or auto-vectorization, so that's a big performance gain just sitting there.

Re: Gonum – Numerical Computing for Go

#18
post #14

Earlier quoted context omitted.

The algorithms are (basically) equivalent, and are translations from the Fortran (though row major instead of column major). As far as I know there are no major differences in the answers, though for extremely poorly conditioned matrices (1e14 or so) you shouldn't expect consistent answers across any implementation. The performance story is complex. Typically we're the same speed on small matrices (and using Go is fa…

I'm surprised your performance is anywhere near that of standard BLAS implementations. The Golang compiler doesn't have support for explicit SIMD or auto-vectorization, so that's a big performance gain just sitting there.

For small vectors and matrices the cgo overhead swamps the assembly speedups. For large vectors cache misses dominate, and the assembly doesn't matter as much. It does matter significantly for medium vectors and large matrices. In that case we provide cgo wrappers and are working on SIMD kernels.

Re: Gonum – Numerical Computing for Go

#19
post #15

Earlier quoted context omitted.

I don't use Gonum with a webserver + large calculations so I can't definitively answer. No one has reported problems, but that could be a lack of usage. One thing though is that matrix multiplication (which is a kernel for higher-level operations) is written in a blocked format, and the code can be pre-empted on any of those blocks, so I wouldn't suspect it's a problem.

Yeah, skimming your source it seems most of your loops involve calling some function, and even if that's inlined I believe the Go compiler will put a speculative yield call in there. I suppose my hypothetical would be an issue if you used a non-Go BLAS implementation, as calling out to C will hog the OS thread. But this is a known issue (e.x. https://www.cockroachlabs.com/blog/the-cost-and-complexity-o... ).

The solution to that is to write a C-batcher. Gorgonia uses that (optional) - https://github.com/chewxy/gorgonia/tree/master/blase

(also it's undergoing major reconstruction/refactoring right now)

Re: Gonum – Numerical Computing for Go

#20

Earlier quoted context omitted.

I have done some numeric programming in Go and compared to Python it's really hampered by the lack of operator overloading. Of course, it just provides convenience, but it's what makes writing stuff in numpy, Tensorflow, Eigen, etc elegant.

As of reading your comment, I'm 100% convinced that Go needs generics. I'm a longtime Go advocate, love coding in Go, but until now thought the lack of generics is just fine. Lately I do a lot of numpy/tensorflow, and have begun to really dislike the slowness of python. It would be great to do that work in Go specifically.

Generics wouldn't necessarily bring in operator overloading, though. I haven't seen a Go proposal for generics that actually included it.
Post reply on HN