5 ms·
Those manual use/optimization of SIMD are done in C anyway. What exactly is so Rust'y in the code? If to compare with C/C++? What is the main benefit of using
by c-smile 10y ago
Those manual use/optimization of SIMD are done in C anyway.
What exactly is so Rust'y in the code? If to compare with C/C++? What is the main benefit of using Rust? Or is it just a test like "you can do that in Rust too"?
- vardump 10y ago> Those manual use/optimization of SIMD are done in C anyway. C seems to be used only for SSE intrinsics support. ~16 LoC of "C". This is all C in the whole project, if you really think you can call it as such: https://github.com/google/font-rs/blob/master/src/accumulate.c https://github.com/google/font-rs/blob/master/src/accumulate... void accumulate_sse(const float *in, uint8_t *out, uint32_t n) { __m128 offset = _mm_setzero_ps(); __m128i mask = _mm_set1_epi32(0x0c080400); __m128 sign_mask = _mm_set1_ps(-0.f); for (int i = 0; i < n; i += 4) { __m128 x = _mm_load_ps(&in[i]); x = _mm_add_ps(x, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 4))); x = _mm_add_ps(x, _mm_shuffle_ps(_mm_setzero_ps(), x, 0x40)); x = _mm_add_ps(x, offset); __m128 y = _mm_andnot_ps(sign_mask, x); // fabs(x) y = _mm_min_ps(y, _mm_set1_ps(1.0f)); y = _mm_mul_ps(y, _mm_set1_ps(255.0f)); __m128i z = _mm_cvtps_epi32(y); z = _mm_shuffle_epi8(z, mask); _mm_store_ss((float *)&out[i], (__m128)z); offset = _mm_shuffle_ps(x, x, _MM_SHUFFLE(3, 3, 3, 3)); } } Also consider top level: https://github.com/google/font-rs/tree/master/src https://github.com/google/font-rs/tree/master/src > What is the main benefit of using Rust? Safety and performance. From the article: "With the SIMD speedup, font-rs is approximately 7.6x faster than FreeType in larger sizes (keep in mind that 42 pixels/em is the default for xxhdpi Android devices)."
- dman 10y agoAny reasons why the sse code wouldnt be written in rust itself?
- phpnode 10y agoNo SIMD intrinsics yet
- kibwen 10y agoOr rather, they're there, but only on nightly builds of Rust, though there's talk of stabilizing them with only minor changes.
- brohee 10y agoThe SIMD crate is still unstable so not usable with the stable compiler, that's the only reason. It should take very little time to convert it to Rust.
- bluejekyll 10y agoIt's the Iterators that make the big difference. Stack based iteration is a huge performeance gain that rust programs have. You might have missed that in his post.
- brohee 10y agoTo add to that, it's likely a huge performance gain because doing it on the stack instead of allocating on the heap improves cache locality quite a bit.
- aidenn0 10y agoFirstly, the graph clearly shows huge gains across point sizes without SIMD optimizations enabled. One of the big gains mentioned in the article for Rust was using iterators instead of a one-time-use vector, which is very hard in C, would currently be best done with Boost in C++, but is a core idiom in Rust. For optimized real-world code, the innermost, hottest, loop is almost always machine-specific, and a superset of C is used if the language of implementation doesn't have intrinsics for the particular machine feature one wants to access. I have only dabbled in Rust, but it is common to see other high-level languages where given X amount of effort the high-level language implementation is faster than a C implementation that could be implemented with a similar amount of effort. It's almost certainly possible to create an iterator version with a custom stack allocator in C that matches the performance of the Rust version, but you will be creating an ad-hoc, informally specified, buggy version of two of rust's core features[1]. C++ is a different beast entirely as the language is on track to completely reinvent itself every 6 years, so it's likely in a few years that you could port the Rust version nearly unchanged to C++17 or C++20, and there's probably a Boost library that allows it now. 1: https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
- fsloth 10y ago"iterators instead of a one-time-use vector, which is very hard in C, would currently be best done with Boost in C++, but is a core idiom in Rust." Maybe misundestood somethin. But hard or requiring boost? Isn't this basically what you meant? class enumerating_parser { uint8_t* pos; uint8_t* end; enumerating_parser(const uint8_t* bytes, int len):pos(), end(pos + len){} bool next(ParserResult& out){ if(pos == end) return false; // do parsing here and move pointer forward } };
- Rusky 10y agoHard in C, which your example is not, and which FreeType is.
- fsloth 10y agoNo, it's pretty much the same in C[0]. Sorry, my point was not laid out. It was not to be obnoxious, but that one can implement various pattern fairly succintly in C or C++ and thus "is difficult to do in language x" is not a very compelling argument there. Rust has algebraic datatypes, memory safety, pattern matching, etc, - those are actual things that are, if not hard, then at least tiringly verbose to do in C and C++; 0: enumerating_parser now becomes struct enumerating_parser{}, the constructor becomes a factory function while next() takes in the parser as a state parameter.
- dikaiosune 10y agoThis thread (https://www.reddit.com/r/rust/comments/4vqpxx/inside_the_fastest_font_renderer_in_the_world/d60so4g https://www.reddit.com/r/rust/comments/4vqpxx/inside_the_fas...) on the Rust subreddit includes a comment from the author regarding using the SIMD functionality in nightly Rust: "Oooh, it's made a lot of progress recently! Funny thing, I actually started experimenting with this stuff pre-Rust 1.0. Last I looked at the SIMD crate, it was missing a whole bunch of stuff, and my style is to use fairly exotic SIMD instructions when they can help (for example, _mm_shuffle_epi8 is available in tmmintrin.h but not pmmintrin.h. This is a technology demo, so using a not-yet stabilized feature seems in scope. Perhaps I'll try the SIMD crate for writing the ARM version."