-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Changed TensorSpan and ReadOnlyTensorSpan layout for better performance. #103244
Conversation
Note regarding the
|
1 similar comment
Note regarding the
|
Tagging subscribers to this area: @dotnet/area-system-numerics-tensors |
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Outdated
Show resolved
Hide resolved
@tannergooding did you have any more feedback on this one? |
|
||
namespace System.Numerics.Tensors | ||
{ | ||
internal readonly struct TensorShape |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this also be a ref struct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to be able to use the same struct as part of Tensor<T>
so we can avoid additional allocations for common cases there as well.
{ | ||
internal readonly nint[]? _metadata; // 8 bytes | ||
|
||
internal readonly nint _memoryLength; // 8 bytes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the layout and size concerns of this change, does the new type require an explicit StructLayoutAttribute
annotation? Are we ok with using the default layout? Is there an expectation that the fields will be consumed by unmanaged code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct contains a managed field (nint[]? _metadata
) and as such is not blittable and will never have StructLayout
respected, the runtime will treat it as Auto
regardless (you can technically mark it as LayoutKind.Explicit
and that would be respected, but that's a de-optimization and would cause many other issues).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct contains a managed field (
nint[]? _metadata
) and as such is not blittable and will never haveStructLayout
respected, the runtime will treat it asAuto
regardless (you can technically mark it asLayoutKind.Explicit
and that would be respected, but that's a de-optimization and would cause many other issues).
Does Mono behave the same? I think it might respect Sequential for managed types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Mono behave the same? I think it might respect Sequential for managed types.
That doesn't really matter. RyuJIT doesn't and so code cannot depend on the managed side being sequential, that is part of why we must use InlineArray
(rather than declaring n-sequential fields).
This is likewise an internal struct, so it can't be used by developers in interop scenarios. Due to it being a struct containing a managed field, it likewise couldn't be used in interop without marshalling and so there is zero benefit to changing the layout from its default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Mono behave the same? I think it might respect Sequential for managed types.
That doesn't really matter. RyuJIT doesn't and so code cannot depend on the managed side being sequential, that is part of why we must use
InlineArray
(rather than declaring n-sequential fields).This is likewise an internal struct, so it can't be used by developers in interop scenarios. Due to it being a struct containing a managed field, it likewise couldn't be used in interop without marshalling and so there is zero benefit to changing the layout from its default.
Yeah but I've meant that Auto could maybe still be beneficial for Mono.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mono should likely consider adjusting their layout algorithm to match the RyuJIT algorithm in that scenario.
There are thousands of structs across the BCL and we are not going to go and annotate every single one of them to be explicitly Auto
because they contain some managed field.
@@ -109,12 +103,8 @@ public ReadOnlyTensorSpan(T[]? array, int start, scoped ReadOnlySpan<nint> lengt | |||
ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); | |||
} | |||
|
|||
_flattenedLength = linearLength; | |||
_memoryLength = array.Length; | |||
_shape = new TensorShape(array.Length - start, lengths, strides); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I wonder if some of the validation logic could be in a helper on TensorShape
-- Not needed to fix in this PR, just a possible simplification opportunity
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorShape.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gave some nits, but nothing that should block this being merged
d275019
to
63bc01d
Compare
/ba-g suppressing unrelated test failure to merge ahead of snap. |
…ce. (dotnet#103244) * TensorShape * fixed TensorShape issue * removed extra inline buffer type. Fixed tests. Added large dimension testing * removed typo * adding unsaved files * changes to use const for stack alloc comparison * changes from pr comments
Changed TensorSpan and ReadOnlyTensorSpan layout for better performance. This included making a new span to hold all the shared data between them and allowing for allocation free behavior for dimensions less than 6.