I don't know if they decided, and if so how, based on this trip report: https://www.think-cell.com/en/career/devblog/trip-report-sum...
Whenever a loop processes data whose size is not a multiple of the AVX-512 vector size and/or which is not suitably aligned, it may be necessary to have a loop prologue and/or a loop epilogue.
For AVX-512 it is always possible to implement the prologue and/or epilogue simply by generating different SIMD lane masks for the first and/or the last iterations (when a lane is masked the operation is not executed for that lane, so a non-aligned vector with any number of elements smaller than the maximum number can be processed).
For legacy reasons the current behavior of gcc is far from optimal. Instead of computing the required masks it inserts additional code as prologue and/or epilogue, consisting of AVX or AVX2 instructions.
This work corrects this behavior, resulting in improved performance for the loops with few iterations, where the execution time of the prologue or epilogue code becomes non negligible.
I do not know if gcc is already smart enough to use masking for control flow, but there exists the also free ispc compiler which does it, allowing one to write programs in CUDA style for CPUs with AVX-512, like AMD Zen 4.
SIMD, or Single Instruction, Multiple Data, allows the computer to do the same operation (like adding numbers) on many pieces of data all at once. This is just like if you had multiple pairs of numbers and you could add all pairs together at the same time.
So instead of doing:
1 + 5 = 6
2 + 6 = 8
3 + 7 = 10
4 + 8 = 12
All separately, the computer can do in one go: (1,2,3,4) + (5,6,7,8) = (6,8,10,12)
But what if we don't want to add all pairs of numbers? What if we wanted to keep one of the numbers from the first group the same, and not add anything to it? That's where "masking" comes in.Using the mask (true/yes, true/yes, false/no, true/yes), we tell the computer to only add the pairs where the mask says 'yes', and skip where it says 'no'.
So, instead of getting (6,8,10,12), we get (6,8,3,12) because we told the computer to skip adding anything to the third number in the first group.
sum_masked(mask=(true,true,false,true), a=(1,2,3,4), b=(5,6,7,8)) = (6,8,10,12)
This saves a lot of work. And the problem gets worse as the vectors get larger. AVX-512 vectors are very large so this is significant.(with rephrasing from https://chat.openai.com/?model=gpt-4)
> sum_masked(mask=(true,true,false,true), a=(1,2,3,4), b=(5,6,7,8)) = (6,8,10,12)
Your explanation reads very clearly but should the result here be (6,8,3,12) instead of (6,8,10,12)?This change, as far as I understand, makes handling those 12 be done via a single masked iteration. This is especially important if, instead of 108 elements, you had just 12, where what previously was 12 loop iterations, is now a single bit of code.
(I don't know what the GCC change is though)