logoalt Hacker News

gnufxtoday at 4:20 PM1 replyview on HN

Vectorization doesn't imply SIMD, of course. The first vectorizing compilers were for CDC(?) systems long before SIMD. Today you have SVE in Arm, for instance, distinct from SIMD Neon.

Anyway, I'm familiar with optimizing numeric loops in C (and Fortran) rather than Rust. I've rarely seen simply using SIMD intrinsics work where GCC auto-vectorization didn't with the same semantics (like numeric equivalence in reductions). In most cases you can get away with -fassociative-math, of course, and not sacrifice peak performance, e.g. BLIS passes its extensive tests with it on, but you should check, of course. (GCC also documents the option as necessary to get Arm (Neon?) to vectorize at all.) Most of the time when people tell you how much better the Itel compiler is, it's because it incorrectly defaults to something like -funsafe-math.

Regardless, GCC (like other compilers) will tell you about vectorization with the -fopt-info- options without examining assembler, and you can have some surprises. For instance, you use unsigned in C for loop indices that you know are positive, and see failed vectorization due to "loop not affine", because of C's overflow semantics; use signed types instead.

There's another reason for using properly-optimized numerical libraries (typically BLAS), is that, at least for level three (matrix-matrix) operations. Even if you get the blocking right for the memory hierarchy, you typically won't get peak performance just with vectorization because tricky preloading is needed for the inner loops.


Replies

jvanderbottoday at 6:26 PM

You're right. In rust, IMHO, the problem is mostly solved by using system C libraries rather than trying to force Rust into something that looks like the optimized C/Fortran we've had for decades. In almost all cases, it's quite possible and quite painless to do it that way. For example, by just making it a matrix operation and letting the system wrapper library call out to something blas-like.