Skip to content
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

Merged
merged 7 commits into from
Jun 20, 2024

Conversation

michaelgsharp
Copy link
Member

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.

Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
Copy link

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-numerics-tensors
See info in area-owners.md if you want to be subscribed.

@ericstj
Copy link
Member

ericstj commented Jun 19, 2024

@tannergooding did you have any more feedback on this one?


namespace System.Numerics.Tensors
{
internal readonly struct TensorShape
Copy link
Member

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?

Copy link
Member

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
Copy link
Member

@eiriktsarpalis eiriktsarpalis Jun 19, 2024

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.

Copy link
Member

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).

Copy link
Contributor

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).

Does Mono behave the same? I think it might respect Sequential for managed types.

Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

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);
Copy link
Member

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

Copy link
Member

@tannergooding tannergooding left a 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

@michaelgsharp
Copy link
Member Author

/ba-g suppressing unrelated test failure to merge ahead of snap.

@michaelgsharp michaelgsharp merged commit 4cfc93b into dotnet:main Jun 20, 2024
75 of 83 checks passed
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
…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
@github-actions github-actions bot locked and limited conversation to collaborators Jul 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants