6 ms·
I'm not familiar with some of these operations. I don't know what a Rust "slice" is. Or what "Zip" does. Could someone show me the most straight forward equiva
by forrestthewoods 10y ago
I'm not familiar with some of these operations. I don't know what a Rust "slice" is. Or what "Zip" does.
Could someone show me the most straight forward equivalent in vanilla C? I assume there is no direct equivalent as temporary storage will be needed. But that's fine and would further serve the purpose of explaining why Rust is cool.
Thanks.
- steveklabnik 10y agoA slice is a pointer + a length. Zip takes two iterators and gives an iterator that returns pairs of elements from each of them. For an imperative translation see https://www.reddit.com/r/programming/comments/5fpghn/zerocost_abstractions/dam19ax/?st=iw5lpml6&sh=4c17bb07 https://www.reddit.com/r/programming/comments/5fpghn/zerocos... Doing an exact translation to C is hard. The C that does the same thing, or C that demonstrates these abstractions that are boiling away?
- kutkloon7 10y agoThe thing with C is also that it's hard to do metaprogramming. Example, I have some finite element code that ideally, I would like to run for an arbitrary dimension. In C, this is practically impossible to code efficiently, while in C++ (and I suppose in Rust) I belive this can be done with templates (though I have not too much experience with this).
- thenewwazoo 10y agoUh, the C equivalent might be something like uint32_t *buffer = ...; uint64_t coefficients[12] = {...}; uint16_t qlp_shift = ...; uint32_t *bufp = &buffer[...]; uint64_t sum; for (size_t i = 0; i < 12; i++) sum += coefficients[i] * bufp[i-12]; uint64_t prediction = sum >> qlp_shift; *bufp += (uint32_t)prediction; Edit: this is incorrect
- kutkloon7 10y agoWhich -in my opinion- is a lot clearer than the Rust code in the article.
- thenewwazoo 10y agoThat's totally fair, but that may have something to do with how well you know Rust. I obviously don't know your familiarity level, but once your mental models "snap" out of thinking about moving data around, and start thinking about operations upon the data, it gets really intuitive.
- deleted 10y ago[deleted]
- khedoros1 10y agoI've seen Rust written in imperative style, and it was clear to me in most of the cases. I think it's more the difference between imperative and functional styles that's throwing people for a loop.
- Gankro 10y agoYeah this is clearly someone who's into FP. If you rewrite this code to replace the map/sum with a for loop it's basically identical in length, while being completely idiomatic.
- bluejekyll 10y agoIt took me some tome to embrace this style in Rust, but now o love it. It cuts down on boiler plate code.
- AnimalMuppet 10y ago> I think it's more the difference between imperative and functional styles that's throwing people for a loop. Pun intended? If so, nicely done.
- kutkloon7 10y ago
- Manishearth 10y agoThis is incorrect. The C code is more like for (size_t i = 0; i < 12; i++) { sum = 0; for (size_t j = 0; j < 12; j++) sum += coefficients[j] * bufp[i + j]; buffer[i + 12] += sum >> qlp_shift; }
- thenewwazoo 10y agoWhoops! You're totally right. I missed the outer loop. Thanks for the correction.
- nkurz 10y agoI think this is still a little off. Maybe you used bufp[i + j] where you meant buffer[i + j]? I may have something wrong too, but I probably would go with: for (size_t i = 0; i < 12; i++) { int64_t sum = 0; int32_t *bufp = buffer + i; for (size_t j = 0; j < 12; j++) sum += coefficients[j] * bufp[j]; *bufp += (int32_t)(sum >> qlp_shift); } I think this will put it in a form where the compiler should vectorize it[1], probably making the loop about twice as fast as the version shown: 3 vector loads, 3 vector multiplications, 3 vector additions and a horizontal sum versus 16 scalar loads[2], 12 scalar multiplications and 12 scalar additions. [1] I presume the "various reasons the above snippet is not as obvious to vectorise as it might seem at first sight" is because the coefficients[] are 64-bit and buffer[] is 32-bit. But a smart compiler should be able to use PMOVSXDQ (packed move sign extend double-word to quad-word) here. Unless there is some other issue, I think the author may be underestimating the benefit of vectorizing here. [2] While the author is right that most of coefficients stay in registers, there isn't actually room for all 12, so 4 of them are loaded from the stack every iteration. Since only 3 128-bit vector registers are required, they should remain there. I'm not sure if the excess loads are actually a bottleneck, though.
- jdub 10y agoThis whole thread: C is fine. We're fine. Everything's fine here now. How are you?
- 10y ago
- Lev1a 10y agozip is a function/method (depending on the language used) that transforms lists of values into A LIST of (n-)tuples of values ending IIRC when the shortest list ends. For example: https://is.gd/hrUf7q https://is.gd/hrUf7q