11 ms·
I was wondering if perhaps this was actually measuring a difference between LLVM and GCC, but they also provide a set of benchmarks of C Clang vs C GCC (1) and
by harporoeder 6y ago
I was wondering if perhaps this was actually measuring a difference between LLVM and GCC, but they also provide a set of benchmarks of C Clang vs C GCC (1) and Clang is generally slower in those test. Although there is some correlation between the ones Clang wins in C And Rust.
1. https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/c.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- indolering 6y agoThe Rust vs C Clang comparison [1] has Rust winning on every benchmark except pidigits, and that's only by .01 seconds. Memory usage and binary size is competitive as well. [1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/rust-clang.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- arcticbull 6y agoRust can be faster than C because in general C compilers have to assume that pointers to memory locations can overlap (unless you mark them __restrict). Rust forbids aliasing pointers. This opens up a whole world of optimizations in the Rust compiler. Broadly speaking this is why Rust can genuinely be faster than C. Same is true in FORTRAN, for what it's worth.
- alerighi 6y agoWell you are saying that even in C you can use the restrict keyword to tell the compiler that 2 memory locations can overlap. Of course is in the hand of the programmer to tell the compiler to do so. I don't think there is a fair comparison between Rust and C: C is just an higher level assembler, if the programmer knows what he's doing he can use the hardware 100% of its potential. That is the reason why C is still used in all the embedded applications where you have ridiculous low power microcontrollers and you must squeeze out the best performance. That is the difference between C and Rust to me: for each fast Rust program you are guaranteed that you can write an equivalent performant program in C (or assembly). Worst case scenario you use inline assembly in C and you get that. Thus the contrary cannot be true for Rust: if I give you a heavily optimized C program not always you can produce an equivalent version in Rust. Also not always these optimizations are what you want. In C you can choose the level of optimizations, and most of the time, at least on the program that I write, I choose a low level of optimization. The reason is that a lot of time performance is not the only thing that matters, but it maybe matters most the stability of the code (and a code compiler with optimizations is more likely to contain bugs) or the ability to debug (and thus the readability of the assembly output of the compiler). Rust gives out an horrible assembly code, that is impossible to debug, or to check for correctness. You just have to hope that the compiler doesn't contains bugs. For the same reason Rust is the ideal language to write viruses, since it's difficult to reverse engineer.
- pjmlp 6y agoPeople think C is an high level Assembler, that was only true on PDP-11, 8 and 16 bit CPUs. Also in C you cannot retrofit restrict in existing programs, specially they depend on existing binary libraries.
- arcticbull 6y agoI think you'd be hard pressed to find more than a handful of usual C programmers, even in embedded, who know what the __restrict keyword does, let alone are rigorous in its application.
- steveklabnik 6y agoI've always wondered if the reason why Rust keeps running into llvm bugs around restrict is that it is used so sparingly, and the semantics being unclear enough, that these codepaths just aren't exercised as often.
- pjmlp 6y agoBesides the previous answer, it isn't supported by ISO C++ (although it does exist as extension), because the majority of the WG thinks it will go the same way as register and inline in the long run.
- steveklabnik 6y ago> Thus the contrary cannot be true for Rust: if I give you a heavily optimized C program not always you can produce an equivalent version in Rust. Do you have some evidence here? Or something more specific? (The rest of your comment is opinions, which you can of course have, but does not match my personal experience, FWIW.)
- pjscott 6y ago> Well you are saying that even in C you can use the restrict keyword to tell the compiler that 2 memory locations can overlap. Of course is in the hand of the programmer to tell the compiler to do so. It says that they can't overlap, but yes, you can get the compiler to optimize based on this if you provide the aliasing information and remember to keep it accurate. You probably won't do that, though, for anything except the most performance-critical of inner loops. A compiler that can infer more about aliasing can provide more optimization, safely, in the >99% of code that doesn't have explicit aliasing annotations, and that's probably worth some decent speedups in practice. There are two main things you might be talking about when you call a programming language fast: 1. Given some really performance-critical code and enough time to hand-optimize it, how close can you get the compiler's output to the optimal machine code? 2. If you write code normally, not making any effort to micro-optimize, how fast will it usually be? Both of these matter. #1 matters when you've got some bottlenecks that you really care about, and #2 matters when you've got a flatter profile -- and both situations are common. Another illustrative example of the #2 type of performance with Rust is the default collections compared to the ones in C++. Rust's default HashMap is faster than C++'s std::unordered_map because of some ill-advised API constraints in the C++ STL. You can get similar performance by using a custom C++ hash table implementation, and in fact Rust's HashMap is a port of a C++ hash table that Google wrote for that purpose, but most people probably won't bother. So, a semantic question: if you can get the same speed in one language as you can in another, but in practice usually don't, is one language faster than the other?
- walki 6y ago> C compilers have to assume that pointers to memory locations can overlap, unless you mark them __restrict... What I don't fully understand is: "GCC has the option -fstrict-aliasing which enables aliasing optimizations globally and expects you to ensure that nothing gets illegally aliased. This optimization is enabled for -O2 and -O3 I believe." (source: https://stackoverflow.com/a/7298596 https://stackoverflow.com/a/7298596) Doesn't this mean that C++ programs compiled in release mode behave as if all pointers are marked with __restrict?
- jart 6y agoNot for char. Compiler always assumes non-restrict for char pointers and arrays, which is important to remember if you're ever operating on a RGB or YCbCr matrix or something.
- bsder 6y agoHuh. Does that also hold for a "uint8_t"--which is often just a renamed unsigned char rather than being a genuine type of its own?
- murderfs 6y agorestrict and strict aliasing have to do with the same general concept, but aren't the same. They both have to do with allowing the compiler to optimize around assuming that writes to one pointer won't be visible while reading from another. As a concrete example, can the following branches be merged? void foo(/*restrict*/ bool* x, int* y) { if (*x) { printf("foo\n"); *y = 0; } if (*x) { printf("bar\n"); } } Enabling strict aliasing is effectively an assertion that pointers of incompatible types will never point to the same data, so a write to y will never touch *x. restrict is an assertion to the compiler on that specific pointer that no other pointer aliases to it.
- tick_tock_tick 6y agoIn theory one day Rust will but LLVM doesn't support anything beyond the function level for noalias since that's all that's needed to support __restrict in C. Even that isn't used by Rust most of the time since they have found several bugs in it.
- volta87 6y agoLLVM does support tbaa! and noalias! metadata.
- tick_tock_tick 6y agohttps://github.com/rust-lang/rust/issues/54878 https://github.com/rust-lang/rust/issues/54878
- shepmaster 6y agoWhy does the Rust compiler not optimize code assuming that two mutable references cannot alias? —https://stackoverflow.com/q/57259126/155423 https://stackoverflow.com/q/57259126/155423
- arcticbull 6y agoFollow along here for re-enabling: https://github.com/rust-lang/rust/issues/54878 https://github.com/rust-lang/rust/issues/54878 For what it's worth I did say "can be" not "is" because I wasn't sure of the current state of this feature. I was just passing on the theory. There are certainly other potential reasons, for instance constant expressions and generics. And, of course, the prohibited undefined behavior makes other optimizations possible, and potentially better.