Some methods in System.Runtime.Intrinsics.X86 don't have overloads for certain data types. For example:
long u1 = 12L,
long u2 = 14L;
var vectorOne = Vector128.Create(u1);
var vectorTwo = Vector128.Create(u2);
var mask = Sse2.MoveMask(Sse2.CompareEqual(vectorOne, vectorTwo))
...
While this is expected as there is no hardware instruction for them. Is there anything I can do as a workaround to compare, in this case, two Vector128 of data type long using Sse2? Such as reinterpreting, casting, different APIs?
If you only care about equality/inequality then yes, you can reinterpret vectors to use a different integer type. Otherwise you should be able to use Subtract and then MoveMask to extract the sign bits.
Thanks, I've tried reinterpreting it as double as I thought it needs to have the same amount of 8 bytes in memory but that didn't worked in some cases. Using an integer type as you said however works fine.
I'm also checking for CompareGreaterThan and CompareLessThan. Can you show me a short code example how I can compare them then?
Thanks, I've tried reinterpreting it as double as I thought it needs to have the same amount of 8 bytes in memory but that didn't worked in some cases. Using an integer type as you said however works fine.
Yes, floating point compares cannot be used in this case because floating point has various special values (NaN, negative 0 etc.).
I'm also checking for CompareGreaterThan and CompareLessThan. Can you show me a short code example how I can compare them then?
If you're not concerned about integer overflow then LessThan is pretty simple: x < y iff x - y < 0 and x - y < 0 iff signbit(x - y) = 1. To get the sign bits:
C#
Sse2.MoveMask(Sse2.Subtract(v1, v2).AsByte()) & 0x8080
Now it depends what do you want to do with the result. Perhaps you don't really need MoveMask, perhaps you need the result in vector format, like normal vector compares provide?
I have a byte array which I iterate through and trying to find matches for a specific value, which itself can be in various data types T, such as long. Matches can be either based on equality, or bigger or smaller. To gain maximum performance I'm casting the byte array into a span of vector128
But I also need to save the position of the match in the original byte array, as well as the matched value as data type T. For this I'm using MoveMask and then TrailingZeroCount and IsBitSet from the BitOps class. This is what I've seen in this repo once and all together is 2-4x times faster than reinterpreting the original byte array as an array of long and iterate through it with a simple loop.
If I just compare two vectors I know if I got a match, but I dont know which of the elements in the vector triggered the match. And calling GetElement for all of them is slower than MoveMask and only call GetElement when needed. Please tell me when I'm wrong and there is a faster and easier way.
cc: @tannergooding
Using MoveMask to get the element which triggered the match and BitOperations.LeadingZeroCount or BitOperations.TrailingZeroCount (the former hardware accelerated on more computers) to get the index of that byte is likely the right thing to do here.
We do similar things in the SpanHelpers class.
Okay thanks :+1: I'm closing this then.