4 ms·
That pattern of doing something for the tail (and possibly also the head, if you're on a platform where aligned loads are preferred or required) of your data is
by hansvm 2y ago
That pattern of doing something for the tail (and possibly also the head, if you're on a platform where aligned loads are preferred or required) of your data is very common in SIMD linear algebra. It's so common that my default way of writing those things is:
1. Write a function implementing the happy-path SIMD
2. (eventually) Write a function implementing the cleanup code
3. (eventually) Implement the final result by appropriately calling into (1) and (2)
That gives you a few benefits. Notably, every problem in TFA (other than the inlining limit) magically goes away. Also, in the vast majority of problems, your cleanup code is itself a valid solution to the problem and also easy to understand, so for free you have a correct implementation to fuzz your fast implementation against (a testing pattern I highly recommend with all optimized code).
Most importantly though, 99 times out of 100 I actually don't need (2) or (3). You can push the padding and alignment constraints all the way to the top level of your program, and the rest of your code can work on slices of vectors instead of slices of floats (or whatever other safe representation you want to choose). The resulting code is much easier to maintain, and the compiled binary is usually smaller and faster.
- goyel 2y agoIn c++, I would write a single template for both paths, and make the compiler generate two functions for each case, so the ifs and checks are automatically removed. Then I would call each function with a parameter like "bool boundary". It's more maintainable
- jesse__ 2y agoSo (2) in this case would be the scalar version of the function that takes a starting pointer, row stride, channel stride, and a row_length and channel_length. By setting the strides to 1 and lengths to max you effectively tell that function the whole matrix is leftovers and it just does the whole computation. Correct?
- hansvm 2y agoThat's not the only option, but it's very reasonable and almost certainly the thing I'd start with, maybe the thing I'd finish with. You then pass an appropriate sub-matrix to this thing which does a whole-matrix computation, and that's the entire "add another loop" trick from TFA.
- jesse__ 2y agoYeah, got it. Thanks for the explanation
- grandempire 2y agoThis is actually a great way to write code in general. Write the happy function. Then write various wrappers to handle all the ugly checks and transforms to get it on the happy path.