5 ms·
The reason the C++ code looks simple is that it uses OpenMP #pragma parallel for, which is a very easy way of doing very simple loop parallelization. By contra
by exDM69 7y ago
The reason the C++ code looks simple is that it uses OpenMP #pragma parallel for, which is a very easy way of doing very simple loop parallelization.
By contrast the Rust example uses parallel iterators from the Rayon crate. If the C++ example had something similar using a C++ library, it would probably be worse.
It's not Rust vs. C++, it's OpenMP directives vs. explicitly writing multithreaded code.
- blub 7y agoThe calls starting with par_ are by far not the biggest readability problem. The Rust code has a lot of noise, whereas the C++ reads like almost like a straight C implementation that anyone could understand.
- exDM69 7y agoWould you like to point out specific instances of this "noise"? The C++ code looks like straightforward "C code" because it's using the OpenMP parallel for. If it dealt with threads explicitly it would not look as pretty. I do agree that the Rust code has some verbosity, for example there are a lot of type annotations and using named constants instead of magic values. For example (C++): int na = (n + 8 - 1) / 8; Versus (you could write this like the above too): let vecs_per_col = (n + simd::f32x8_LENGTH - 1) / simd::f32x8_LENGTH; An example of the type annotations (are they really necessary?): let pack_simd_row = |(i, (vd_stripe, vt_stripe)): (usize, (&mut [f32x8], &mut [f32x8]))| { Comparing the actual internals of the algorithm is quite straightforward, e.g. look at the middle loop (lines 70-82 in Rust vs. 58-97 in C++). Do note that the C++ code is loop unrolled by hand which makes it look simpler. In the Rust code, there's a pretty cool feature where multithreading can be toggled on/off with a compile time flag, see parts with: #[cfg(not(feature = "no-multi-thread"))] If the C++ example wouldn't use OpenMP, this would be pretty impossible to achieve without being noisy too. Also note that even with OpenMP, it would be quite easy to create a memory unsafety issue in the C++ code by for example accessing an array out of bounds inside the loop body. Apart from these, I have no problems reading and understanding the C++ or Rust code (and I'm a noob with Rust).
- imtringued 7y agoFrom what I have read Rust users don't seem to care about OpenMP at all. Some even go as far to say that they would prefer using something like a Rayon alternative for C++ instead.
- exDM69 7y agoIt's not obvious how the hypothetical OpenMP for Rust should work. If you'd put #pragma omp parallel for in front of a loop, there would be no compile time guarantees of memory safety or freedom from data races. OpenMP is suitable for the most simplest kind of parallelism in the first place. If you look at the example code here, there's like 5 lines of pretty simple Rayon code that's almost a drop-in replacement for single threaded iterator code. It performs almost as good as the OpenMP C++ code, and it's guaranteed to be safe.
- gpderetta 7y agoWell, the whole purpose of OpenMP is to be a syntactically lightweight way of parallelizing code; it is a well supported standard. C++17 in fact has paralel extensions to the standard library, but if you have access to OpenMP it is often better. OpenMP is not C++ specific, it is also supported in fortran and C (although the newer OpenMP standards have first class support for C++ iterator semantics). In principle it could also be supported in rust although I assume that making it work with the borrow checker might not be easy.