-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SpanExtensions.AsVector #23688
Comments
Is converting your |
Don't need the public static Vector<T> AsVector<T>(this Span<T> slice) where T : struct
{
if (slice.Length < Vector<T>.Count) throw new ArgumentOutOfRangeException();
return Unsafe.As<T, Vector<T>>(ref slice.DangerousGetPinnableReference());
} What would the usage be? Something like: while (span.Length >= Vector<byte>.Count)
{
var vec = span.AsVector();
// stuff with vec
span = span.Slice(0, Vector<byte>.Count);
}
Something like? var vectorSpan = span.NonPortableCast<byte, Vector<byte>>();
for(var i = 0; i < vectorSpan.Length; i++)
{
var vec = vectorSpan[i];
// stuff with vec
} |
Right, and then you could just read and write directly to the indexer. vectorSpan[i] ^= mask;
vectorSpan[i] += vectorSpan[i + 1];
// Etc. |
Merging the two... What about public static Span<Vector<T>> AsVectorSpan<T>(this Span<T> slice) where T : struct
{
return slice.NonPortableCast<T, Vector<T>>();
} |
With the earlier example: while (span.Length >= Vector<byte>.Count)
{
Vector<byte> vec = span.AsVector();
// stuff with vec
span = span.Slice(0, Vector<byte>.Count);
} presumably it's followed by a loop on the remaining bytes: while (span.Length >= Vector<byte>.Count)
{
Vector<byte> vec = span.AsVector();
// stuff with vec
span = span.Slice(0, Vector<byte>.Count);
}
for (int i = 0; i < span.Length; i++)
{
// stuff with span[i]
} What does that look like with this |
I think it would be something like this: Span<T> span;
Span<Vector<T>> vSpan = Convert(span);
for (int i = 0; i < vSpan.Length; i++)
{
// Do stuff with vSpan[i]
}
span = span.Slice(Vector<T>.Count * vSpan.Length);
for (int i = 0; i < span.Length; i++)
{
// stuff with span[i]
} |
Depends if slice first or hard fail on conversion var vSpan = span.Slice(0, span.Length % Vector<byte>.Count).AsVectorSpan();
for(var i = 0; i < vSpan.Length; i++)
{
var vec = vSpan[i];
// stuff with vec
}
span = span.Slice(Vector<byte>.Count * vSpan.Length);
for (int i = 0; i < span.Length; i++)
{
// stuff with span[i]
} or as part of a Try call that does a partial amount if (span.TryAsVectorSpan(out var vSpan))
{
for (var i = 0; i < vSpan.Length; i++)
{
var vec = vSpan[i];
// stuff with vec
}
span = span.Slice(Vector<byte>.Count * vSpan.Length);
}
for (int i = 0; i < span.Length; i++)
{
// stuff with span[i]
} With a public static bool TryAsVectorSpan<T>(this Span<T> slice, out Span<Vector<T>> vectorSpan) where T : struct
{
var count = slice.Length % Vector<byte>.Count;
if (count > 0)
{
vectorSpan = slice.Slice(0, count).NonPortableCast<T, Vector<T>>();
return true;
}
vectorSpan = default;
return false;
} May also have predetermined fixed sized Vector processing that has no extra elements public static Span<Vector2> AsVector2Span(this Span<byte> slice)
{
return slice.NonPortableCast<byte, Vector2>();
}
public static Span<Vector3> AsVector3Span(this Span<byte> slice)
{
return slice.NonPortableCast<byte, Vector3>();
}
public static Span<Vector4> AsVector4Span(this Span<byte> slice)
{
return slice.NonPortableCast<byte, Vector4>();
} Probably the extensions should live in namespace |
for (var i = 0; i < vSpan.Length; i++)
{
var vec = vSpan[i];
vec ^= mask;
vSpan[i] = vec;
} Though it may lead to more direct operations on the Vector elements, so shunting from memory and registers more? |
@KrzysztofCwalina, is the proposal ready for review? |
We should align it with the existing APIs, so I'd rather make this a ctor on namespace System.Numerics
{
public struct Vector<T>
{
// Existing API
public Vector(T[] values);
// Proposed API
public Vector(Span<T> values);
}
} |
FYI: The API review discussion was recorded - see https://youtu.be/BI3iXFT8H7E?t=5251 (11 min duration) |
Top post updated with approved API shape above https://github.com/dotnet/corefx/issues/24343#issuecomment-349418624. |
To make sure I understand the ask and, the conclusion in the recording... this is a constructor that "copies" the contents of the span into the vector; no re-interpretation of span's is expected here...
|
* CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
* CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
* CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
* CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
* CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 * CoreFX #24343 Vector using Span dotnet/corefx#24343 Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
Final/Approved Proposal
https://github.com/dotnet/corefx/issues/24343#issuecomment-349418624
Original Proposal
It's quite common to want to convert a Span to Vector. It's possible to open code such conversion, but the code is a bit tricky and people do it commonly enough that we shoudl just add a helper to SpanExtensions
cc: @jkotas, @mellinoe, @ahsonkhan, @benaadams, @stephentoub
The text was updated successfully, but these errors were encountered: