I'm looking into Vector<T>
in the System.Numerics.Vectors namespace from version 4.5.0-preview1-26216-02. MSDN documentation says:
Vector<T>
is an immutable structure that represents a single vector of a specified numeric type. The count of aVector<T>
instance is fixed, but its upper limit is CPU-register dependent.
https://learn.microsoft.com/en-us/dotnet/api/system.numerics.vector-1 (emphasis added)
Even overlooking the misguided wording "count [sic.] of a Vector", this sentence seems quite unclear, since it implies that different Vector<T>
instances might have different--albeit "fixed" up to some CPU-limit--"counts" (again, so-called 'count' of what, exactly?) There's no mention of an actual Count
property here--or in fact anywhere on the intro page).
Now normally, I think "read-only" or "immutable" are more conventionally used than "fixed" for describing an instance's properties or fields, but in this case it turns out that the Vector<T>.Count
property, while indeed read-only, is also static, and thus in no-way associated with any Vector<T>
instance. Instead, its value varies only according to the generic type argument T
(and then presumably from machine-to-machine, as indicated):
bool hw = Vector.IsHardwareAccelerated; // --> true
var c = (Vector<sbyte>.Count, Vector<short>.Count, Vector<int>.Count, Vector<long>.Count);
Debug.WriteLine(c); // --> (16, 8, 4, 2)
Oh.
So is it basically System.Int128
in disguise? And is that it? My questions are:
- Am I missing something? It's true that I knew
littlenothing aboutSIMD
, but I thought this library would allow the use of much wider hardware-accelerated datatypes than just 128 bits. My HPSG parsing engine routinely performs intensive bitwise computations vectors of 5,000+ bits. Again assuming I'm not missing the point, why not just call it
System.Int128
/System.UInt128
instead ofVector<T>
? Parameterizing it with the generic primitive types does pose certain benefits, but gave me the wrong idea that it was more a usefully expansive array (i.e., namely, of blittable elementsT
), as opposed to just a double-width CPU register, which to my mind is about as "scalar" as you can get.Don't get me wrong, a 128-bit register is interesting, useful, and exciting stuff--if just a bit oversold here maybe? For example,
Vector<byte>
is going to have 16 elements no matter what, regardless of whether you need or use them all, so the spirit ofCount
which is expected to vary by instance at runtime seems to be misapplied here.Even though a single
Vector<T>
won't directly handle the use case I described as I was hoping, would it be worth it to update my current implementation (which uses aulong[N >> 6]
array for each N-bit vector) to instead use theVector<ulong>[N >> 7]
array?...yes, that's "array of
Vector<ulong>
", which again seems strange to me; shouldn't a type with "Vector" in its name be sufficiently or usefully extensible without having to explicitly create an array to wrap multiple instances?- Beyond the fact that each 128-bit SIMD bitwise operation is processing twice as much data, are SIMD bitwise operations additionally faster (or slower) in cycles per opcode as well?
- Are there other hardware platforms in common use or availability today where
System.Numerics.Vectors
actually reports a different SIMD bit-width?