Do crates use hardware instructions automatically?

I'm trying to move from Go to Rust. In Go, when I call for example AES functions it will automatically use hardware AES instructions if available. (The library contains hardware and fallback implementations.) Or when I want to use popcnt, there's a library and it will detect and automatically use the hardware instruction.

In Rust it seems to be a bit different? I found some crates for hardware AES and for SIMD instruction sets, but it seems I have to provide fallback implementations and use is_x86_feature_detected! myself?

And then there's target_feature, both as an attribute in the code and as a command line option, but it's not clear to me when I have to use which one?

A crate could implement runtime feature detection to choose between a hardware accelerated and fallback implementation, yes.

Yes, but do they? Is it idiomatic? Do I have to set target-feature on the command line?

After looking at the source in the aes crate, it checks if some flags are set.
If rustc passes those flags on your machine I don't know. But I know how you could find out (just an idea, surely there is a better way):
Take the cfg items from the aes crate and put a println behind, that way you can find out if your rustc sets those flags.

Ah, maybe another explanation helps too:
The compiler (rustc) has a set of flags (the relevant ones in this case are aes and sse2). Using cfg items the behavior of the source code can be altered depending on the presence of those flags.
This is used in the aes crate to either expose a implementation from the aesni (native instructions, aka hardware accelerated) or aessoft (software implementation) crate at compile time. This also implies that no runtime checks are done, but your binary may only run on machines that have sse2 and aes instructions.
If the compiler sets the flags depends. I don't know what the default behavior of rustc is, but remember that when building a program ideally it should run anywhere. This implies that the compiler is limited in the set of flags it can set when building the program (for example not everyone has avx512).

If your cpu has sse2 and aes instructions and the executable only has to run on your computer you could pass "-C target-cpu=native" to rustc.

1 Like

Sorry, but your explanation left me more confused than before. :grin:

So, ok, I have learned that I can pass target-cpu=native to enable the optimizations that work on the compiler's CPU. Unfortunately I'm not really interested in that. A program is almost never run where it was built.

So basically with the aes crate I would have to use aesni and aessoft directly and not use the aes crate at all, otherwise I would have to build multiple binaries for different CPUs?

If I were to use the aes crate (or another one that has similar checks at compile time), what's the default when I don't pass anything? Super accelerated but only runs on certain CPUs or everything in software but runs everywhere?

Yes, if there is no other crate that does that runtime check you will have to do it yourself (haven't looked). This might help you do it.

I don't know the exact defaults of rustc, sorry. As far as I know however the defaults are conservative and should run almost anywhere (I think I read somewhere sse2 is default, but I don't remember where that was)

1 Like

The 64-bit version of the x86 architecture adopted SSE and SSE2 as core features, so any 64-bit program can assume that these instruction sets are available.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.