Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Linear Zoetrope
Nov 28, 2011

A hero must cook

Jo posted:

I'm considering picking up Go as an extra tool. Most of the work I do involves image manipulation, numerics, and machine learning. I saw some discussion on the Go user group saying academics were migrating away from Go, but I'm slightly scrupulous. Is there any reason not to get involved if that's the kind of work I'm doing? What are the de-facto linear algebra and image packs?

I'm one of the owners of Gonum, which isn't super mature right now, but it does have blas bindings and a higher-level matrix package. We also just started a statistics package. It benchmarks pretty well, actually, but you have to remember there's no operator overloading so code looks verbose. It's not quite as bad as you might think. Even in Numpy matrix multiplication is a.dot(b), so compared to packages like that you're not missing much, only really addition/subtraction and scalar multiplication see much use with operator overloading in most other languages.

Image processing itself is a beast because you probably want something with OpenCV-ish functionality, which just doesn't exist in Go. I did some Kinect stuff in Go just to see how it works and it was a mess. Wrapping libfreenect was fairly straightforward, but using the better functionality of OpenCV requires a bunch of Cgo nonsense with wrapping heap allocated matrices in (void*)'s and oh by the way make sure your headers are in pure C and only include pure C, but you can still implement the function in .cxx files which can have C++ and... :psyduck: it's all pretty terrible. (Also: SWIG seems to not play super nice with Open CV for some drat reason)

The thing is Go could be a very good language for this stuff. If you're willing to help write it the potential is there. I knocked out a pretty decent and fast Canny edge detection filter in an hour or so, but if you're just looking for nice frameworks that let you do your work, you need to find a more established language.

spongeh posted:

How is Go for game dev? I've found a couple of bindings, but nobody seems to support SDL2 yet. I seemed to have the impression that even though it's now 1.0, there's not a whole lot of use, but it may be more server-oriented which I'm not really looking at.

It really depends. There's nothing stopping you if you already really like Go. I'm writing an engine in it and it's enjoyable. However, if you're looking to get into go FOR game programming I'd say to stay away from it. I won't enumerate all the minutae (especially if you want an asynchronous engine), but the libraries really aren't there and once you get into graphics and audio drivers you run into... speedbumps with the way the runtime works re: goroutines and threading. The best bindings right now are for pure Open GL, the SDL ones and other "nice" libraries are fairly incomplete or abandoned.

Even audio you'll probably have to resort to wrapping Open AL (most of the currently available wrappers are poo poo) or Port Audio (obnoxious because you have to attenuate and mix audio manually) or something.

Linear Zoetrope fucked around with this message at 11:24 on Aug 10, 2014

Adbot
ADBOT LOVES YOU

Linear Zoetrope
Nov 28, 2011

A hero must cook

I don't personally maintain the LAPACK bindings, so I'm not sure. I could figure it out, but it may be faster to just ask on the Google Group. I'll try to approve you as soon as I can. I do know that I'm the only one in the group that semi-regularly uses anything other than Linux (I have a Mac and a PC that I do dev on pretty frequently), so it's entirely plausible the OS X bindings for LAPACK are just screwed up. LAPACK is a really new package.

Scaevolus posted:

As much as I like Go, Julia is looking more promising for scientific workloads. Go's developers want a language to write networked services, so things like maximal performance (including FFI), good matrix support, and operator overloading aren't particularly high on their list of improvements.

http://www.evanmiller.org/why-im-betting-on-julia.html

Julia probably has a better feature set, and I'll probably use it at some point (I've already done a couple small projects in it). I encourage anyone to use the tools for the job, and Julia fits the bill. Probably better than Go too.

Go is still pretty good, and is especially good at make concurrent, cache-oblivious algorithms painlessly. The main problem I have with Julia is that reading it is a pain, for whatever reason I have trouble parsing Julia code quickly and efficiently. I find it easier to knock out something in Go, and that was true even did when I didn't know the language. There's something about Go's design that agrees with my particular brain and makes it almost effortless to think in the language, in a way I've never had with C++ or Matlab or even Python. It's really a personal preference thing, to me. :shrug:

E: Oh, and I haven't found GC latency to be a big deal for games. If you do some research, Go's GC has fairly predictable criteria for firing, most of it relating to allocating <x> times more memory than the last time the GC ran. So if you front-load all your allocations with some sort of pool it's pretty negligible.

Linear Zoetrope fucked around with this message at 02:16 on Aug 11, 2014

Linear Zoetrope
Nov 28, 2011

A hero must cook

Ninja Rope posted:

Is there a good way to generate bindings for a large C dynamic library? Something with tens of header files and a hundred or so functions, more than I could create or maintain by hand.

That sounds like SWIG's job.

Linear Zoetrope
Nov 28, 2011

A hero must cook
Oh... oh. A slice's capacity upon reallocation by append is not uniform between compiler targets. I kind of knew this, which is why I never rely on underlying buffers being the same or different when it comes to append, but actually seeing it in action is kind of surreal.

code:
a := []int{}
a = append(a, 1)
b := append(a, 1)
Do a and b share the same backing array? Nobody knows! It depends how the compiler decides to grow slices at capacity. (It comes down to the question: at the line where we declare b, is the capacity of a 1 or larger than 1?)

This isn't theoretical, the answer actually changes between the playground and my machine.

Linear Zoetrope fucked around with this message at 12:23 on Dec 27, 2014

Linear Zoetrope
Nov 28, 2011

A hero must cook
It is because you are small

But really, I think it's because it's a type system designed by people largely comfortable in C as a primary language, with a focus on compiling extremely fast.

Linear Zoetrope
Nov 28, 2011

A hero must cook
It is, but it does kind of manage to capture some of the culture on golang-nuts.

Linear Zoetrope
Nov 28, 2011

A hero must cook

sarehu posted:

My real theory is that the compiler is a complete disaster (I looked) so it would be hard to do. I feel like a hypocrite because I'm 1 for 1 when it comes to having your compiler be a disaster, but I can't imagine having to add generics to their existing implementation. I just remember seeing some struct with pages of fields in it, like out of some 80's horror movie. Now they've got it implemented in Go but apparently that was with a C to Go translation so it's probably still the same.

Nah, they've said frequently that they can do it. In fact, forks of the compiler with various generic implementations exist. The issue they always give is that they need an implementation that has:

1. Basically no impact on compile times (and requires no symbol table to parse)
2. A very small (at worse) impact at runtime
3. Is syntactically pleasing in Go

3, of course, gives then carte blanche to deny anything. I think it's 1 that's the sticking point. Their core design absolutely requires that they can compile a Google-sized codebase from scratch in about a minute (assuming no Cgo), but also runs quickly. It's maybe not an impossible situation, but it's extremely unlikely they'll find a good solution with those constraints. The best thing I came up with was a silly proposal I made for fun that tried to be as anally Go as possible (it's essentially "the make keyword for interfaces and functions"), which I think meets most constraints, and should be implementable as a simple extension of make.

Whatever though, I only need it for 3D Linear Algebra which I already resorted to using code generation for.

E: The Plan9 assembly language they use is, indeed, garbage though. Please do not ask me about trying to write SIMD in that thing. It has a lot of dumb quirks. For instance, did you know that you can write an assembly function that takes a value receiver, but NOT a pointer receiver?

It's true. You declare an assembly function like this:

code:
TEXT ·det3(SB),4,$0-12
This is an assembly function, with some flags that evaluate to 4 (not important), with 12 bytes of input/output stack. If you write the stub

code:
func det3(mat *Mat3) float32
The compiler will auto-bind the definition of det3 as that assembly routine. You can also do this on methods.

code:
TEXT ·Mat3·det(SB),4,$0-40
Which corresponds to

code:
func (mat Mat3) det() float32 
Note that the stack is now size 40, because a Mat3 is a 3x3 array of 32-bit float values so we have 36-input, 4-output = 40. But that's giant, if you benchmark it's legitimately slower by a factor of almost 5 to do the copy. So we want to implement it on a pointer.

code:
TEXT ·*Mat3·det(SB),4,$0-12
This won't work. So maybe it's some weird quirk, right? Like how Go uses the cdot · instead of the period in the assembly due to symbol conflicts. Nope. It is literally impossible. It's not even hard to fix, someone found it and fixed it in like a day! But they refused to accept the pull request because they don't want people doing that for... reasons that aren't clear.

So make a passthrough function? Like, maybe

code:
func (mat *Mat3) Det3() float32 {
    return det3(mat)
}
Nope, at the speeds you're working with doing SIMD optimization, the passthrough is almost as slow as the by-value copy. I don't recall my benchmarks off the top of my head, but SIMD-with-pointer is like 2.1 ns/op, SIMD-with-copy is like 10.8 ns/op, SIMD-with-passthrough-by-pointer is like 9.5 ns/op.

I hate everything about working with Go's intermediate assembler.

Linear Zoetrope fucked around with this message at 05:24 on Feb 26, 2015

Linear Zoetrope
Nov 28, 2011

A hero must cook

mdxi posted:

It may be helpful to remember that Go is a language designed at Google, for Google, to solve Google's problems, in a way which is efficacious for Google. It may also be illuminating to remember that it was designed and written by people who are already titans in their field and have absolutely nothing to prove to anyone.

It is basically a pleasant side effect that Go is useful to people outside of Google.

As an aside, if you don't like the design or implementation of a language, you'll feel much better (and get a lot more respect) if you (a) write code to solve a cool problem, in a language which you do enjoy, instead of (b) writing prose to tell the internet that you have decreed a language to be bad.

Eh, I like Go but it has problems. I can go on a rant about any language I use enough to understand. Go's assembly and type system are somewhat problematic, but it has a lot of good aspects. For instance, I can pretty much read anybody's Go code without many problems (unless it's deliberately obfuscated or it's a problem domain I have no experience in), which is actually kind of amazing.

Linear Zoetrope
Nov 28, 2011

A hero must cook

sarehu posted:

go fmt is changing a * b to a*b on me.

I'm getting really hatey right now.

It bundles operators by binding/precedence. It's to make expressions like a * b + c * d easier to read by grouping them as a*b + c*d. It's kind of dumb when it does it on standalone expressions though, yeah.

Linear Zoetrope
Nov 28, 2011

A hero must cook
You think that's bad, try working on a project that needs things like matrices. The `go generate` command has made things a bit easier, but it's extremely silly to have to write your own template generation code to implement the exact same algorithms for float/big/complex/whatever.

(The code can deviate at points; especially for things like constants, but the points where the code diverges are much more sparse than cases where it's identical).

Linear Zoetrope
Nov 28, 2011

A hero must cook

COOL CORN posted:

Go is confusing to me. I just got a coupon code for a Udemy course about it, and it seems super great from the outset, and a lot of companies are using it. But... only 5 pages here, and most of it is complaining about the language. Did it just never get any traction? Is it dying out?

It is very good at certain things. Go is conceptually simple and lightweight. Unfortunately, its devotion to "simplicity" is somewhat slavish which causes some huge problems for certain types of code. It can also cause performance issues because, despite being a compiled language, almost everything generic has to use vtables at best and aggressive type conversion and/or reflection at worst unless you want to roll your own template generation code.

Its interoperability with C is also... idiosyncratic.

Linear Zoetrope
Nov 28, 2011

A hero must cook
Go is basically just really good until it's not. It's amazing to me how easy it is to keep it in your head and read someone else's code, but once you hit a HERE BE DRAGONS area, have fun. One HERE BE DRAGONS area is interoperability with any C library that expects all calls to be on the main thread (like anything involving windowing systems on OS X). You can do it by locking the OS thread in the init function, but you can't really do that as a modular library, it pretty much worms its way into the structure of any program with it as a subdependency.

Adbot
ADBOT LOVES YOU

Linear Zoetrope
Nov 28, 2011

A hero must cook
Note that these assignments are evaluated left to right, though. This is important if your function calls are stateful or there's deadlock potential.

code:
package main

import (
	"fmt"
)

func syncrx(quit chan<- struct{}, sync <-chan struct{}) {
	<-sync
	
	quit <- struct{}{}
}

func synctx(quit chan<- struct{}, sync chan<- struct{}) {
	quit <- struct{}{}
	
	sync <- struct{}{}
}

func main() {
	quit1,quit2,sync := make(chan struct{}), make(chan struct{}), make(chan struct{})
	
	go syncrx(quit1,sync)
	go synctx(quit2,sync)
	
	x,y := <-quit1, <-quit2
	
	fmt.Printf("%v, %v\n", x, y)
}
Playground

Will deadlock because syncrx is waiting on synctx, synctx is waiting on main, and main is waiting on syncrx. Swapping quit1 and quit2 in the assignment will make it run properly.

Linear Zoetrope fucked around with this message at 21:42 on Aug 24, 2018

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply