4 ms·
>one annoyance I have is that it seems there is no middle ground between alright performance using pure Go and great performance using Go with assembler. I don
by klauspost 11y ago
>one annoyance I have is that it seems there is no middle ground between alright performance using pure Go and great performance using Go with assembler.
I don't think it is a Go-specific thing. It just happens that this is an algorithm that lends itself extremely well to assembler, because the 'pshufb' instruction allows you to make 16 16-byte lookups in 3 cycles.
The speedup between Go and assembler is the same as the speedup between C and assembler.
>but bitwise operations are painfully slow compared to the equivalent in C.
I think the biggest difference is in variable shifts, since Intel doesn't have instructions for shifts bigger than (register size - 1). This means that if shift using a non-constant shift, Go has to check if you are shifting more than the register size, and execute special code to do that.
If a = uint64(1) and x = uint(64), then a << b always gives 0 in Go. I believe that in C (at least older C) the result is undefined, and therefore the compiler can choose the fastest option.
Also, being able to skip bounds checks in assembler is of course a (usually) minor speedup.
In general I don't see this as a huge issue, and onlyuse assembler if I know it would bring at least a 2x speedup.
>[...]need to be kept up to date and checked for bugs / errors / inconsistencies
Use build tags. In the reedsolomon package, I can run `go test -tags=noasm` to test if my pure go version passes tests.
>Is it just a matter of waiting for the Go compiler to "level up" optimizations to match GCC/Clang?
GCC has has many, many years in developement, and llvm/clang still isn't better (in my experience). I have battled with buggy code optimizers, and I don't want Go to be there. I want a solid compiler first, and fast secondly.