Fix non-dense TensorSpan handling in SequenceEqual, Fill*, Resize*, IndexOf*, and ConcatenateOnDimension#124225
Conversation
…or spans Co-authored-by: stephentoub <[email protected]>
|
Tagging subscribers to this area: @dotnet/area-system-numerics-tensors |
There was a problem hiding this comment.
Pull request overview
Fixes Tensor.SequenceEqual / TensorSpan.SequenceEqual so that comparisons involving non-dense tensor spans compare only the logical elements (ignoring unobserved gap/padding in the underlying buffer), while preserving the dense fast-path.
Changes:
- Updated
ReadOnlyTensorSpan<T>.SequenceEqualto use a dense fast-path and a non-dense element-by-element slow-path. - Simplified the
TensorSpan<T>overload to delegate to theReadOnlyTensorSpan<T>implementation. - Added unit tests covering non-dense vs non-dense, dense vs non-dense (both directions), differing logical elements, and the
TensorSpan<T>overload.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs | Fixes SequenceEqual semantics for non-dense spans and centralizes logic via the ReadOnlyTensorSpan<T> overload. |
| src/libraries/System.Numerics.Tensors/tests/TensorTests.cs | Adds regression tests validating correct SequenceEqual behavior across dense/non-dense scenarios. |
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs
Show resolved
Hide resolved
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs
Outdated
Show resolved
Hide resolved
|
@copilot do other methods have the same or similar problem? e.g. IndexOf*, ResizeTo, Fill*, etc.? Please investigate and fix any other similar problems in the whole library. |
…dd tests Co-authored-by: stephentoub <[email protected]>
Investigated all methods in the library that use
Methods using |
src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs
Show resolved
Hide resolved
Co-authored-by: stephentoub <[email protected]>
Implemented the follow-up fixes and retried with fresh validation in ec7f3ab. I added a new regression test for |
| // For non-dense destinations, concatenate into a temporary dense buffer, | ||
| // then copy element-by-element to respect the destination's stride layout. | ||
| T[] tempBuffer = ArrayPool<T>.Shared.Rent((int)totalLength); | ||
| try | ||
| { | ||
| Span<T> tempSpan = tempBuffer.AsSpan(0, (int)totalLength); | ||
| ConcatenateOnDimensionToSpan(dimension, tensors, destination, tempSpan); | ||
| ReadOnlyTensorSpan<T> tempTensor = new ReadOnlyTensorSpan<T>(tempBuffer, 0, destination.Lengths, []); | ||
| TensorOperation.Invoke<TensorOperation.CopyTo<T>, T, T>(tempTensor, destination); | ||
| } | ||
| finally | ||
| { | ||
| ArrayPool<T>.Shared.Return(tempBuffer); | ||
| } |
There was a problem hiding this comment.
nit: Getting it working correctly is most important, so I think the temp buffer for right now is ok, but we should have a tracking issue to avoid the temporary buffer since it can add significant expense (due to amount of memory accesses/copying)
| random ??= Random.Shared; | ||
|
|
||
| for (int i = 0; i < span.Length; i++) | ||
| if (destination.IsDense) |
There was a problem hiding this comment.
Similar here. In general this is meant to be handled via the TensorDimensionSpan iterator, which allows getting the contiguous sequences more easily -or- via the TensorShape.AdjustToNextIndex APIs for more complex cases.
|
/ba-g deadletter |
Description
This PR fixes incorrect behavior for non-dense (strided) tensor spans where methods were operating over raw underlying storage rather than logical tensor elements.
In addition to the original
SequenceEqualfix, this now includes follow-up correctness and consistency updates requested in review feedback.Changes Made
SequenceEqualfor non-dense spans to compare logical elements only.FillGaussianNormalDistributionFillUniformDistributionResizeResizeToIndexOfMaxIndexOfMinIndexOfMaxMagnitudeIndexOfMinMagnitudeFlattenedLengthinstead of_shape.LinearLength.SequenceEqualto align withIEquatable<T>.Equalssemantics used by span-based comparisons.IndexOf*Fallbackimplementations to useArrayPool<T>.Sharedinstead of allocating new arrays per call.ComputeLogicalOffsets.ConcatenateOnDimensionbehavior for non-dense destination spans by handling destination layout correctly.TensorConcatenateNonDenseDestinationTestsTesting
./build.sh clr+libs -rc releasedotnet build /t:test src/libraries/System.Numerics.Tensors/tests/System.Numerics.Tensors.Tests.csprojSystem.Numerics.Tensors.Teststotal: 5401Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.