Skip to content

Commit

Permalink
Fixing API to use in and ReadOnly as needed (#103368)
Browse files Browse the repository at this point in the history
* fixing API to use in and ReadOnly as needed

* test fixes

* API updates from Tanner's suggestion

* test fixes

* removed InPlace, changes from PR discussions
  • Loading branch information
michaelgsharp authored Jun 19, 2024
1 parent 33e550a commit 88013cb
Show file tree
Hide file tree
Showing 12 changed files with 2,925 additions and 4,527 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,7 @@
<data name="Argument_IncompatibleDimensions" xml:space="preserve">
<value>Incompatible dimensions for provided tensors. left.Lengths[1] == {0} while right.Lengths[1] == {1}.</value>
</data>
</root>
<data name="ThrowArgument_StackShapesNotSame" xml:space="preserve">
<value>All tensors must have the same shape.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
<Compile Include="System\Numerics\Tensors\netcore\ITensor.cs" />
<Compile Include="System\Numerics\Tensors\netcore\IReadOnlyTensor.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanDebugView.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanExtensions.cs" />
<Compile Include="System\Numerics\Tensors\netcore\ReadOnlyTensorSpan.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.cs" />
<Compile Include="System\Numerics\Tensors\netcore\TensorSpanHelpers.T.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,14 @@ public void FlattenTo(scoped Span<T> destination)
nint copiedValues = 0;
while (copiedValues < _flattenedLength)
{
TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]);
if (Strides[Rank - 1] == 0)
{
destination.Slice(checked((int)copiedValues), (int)Lengths[Rank - 1]).Fill(Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)));
}
else
{
TensorSpanHelpers.Memmove(destination.Slice(checked((int)copiedValues)), ref Unsafe.Add(ref _reference, TensorSpanHelpers.ComputeLinearIndex(curIndexes, Strides, Lengths)), Lengths[Rank - 1]);
}
TensorSpanHelpers.AdjustIndexes(Rank - 2, 1, curIndexes, _lengths);
copiedValues += Lengths[Rank - 1];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;

#pragma warning disable CS8601 // Possible null reference assignment.
Expand All @@ -19,7 +20,6 @@ public static partial class Tensor
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
where T : IEquatable<T>
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
Expand All @@ -33,7 +33,6 @@ public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, bool pinned
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false)
where T : IEquatable<T>
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = pinned ? GC.AllocateArray<T>((int)linearLength, pinned) : (new T[linearLength]);
Expand All @@ -48,7 +47,7 @@ public static Tensor<T> Create<T>(scoped ReadOnlySpan<nint> lengths, scoped Read
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths)
where T : IEquatable<T> => Create(values, lengths, []);
=> Create(values, lengths, []);

/// <summary>
/// Creates a <see cref="Tensor{T}"/> from the provided <paramref name="values"/>. If the product of the
Expand All @@ -60,51 +59,40 @@ public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths)
/// <param name="isPinned">A <see cref="bool"/> indicating whether the <paramref name="values"/> were pinned or not.</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static Tensor<T> Create<T>(T[] values, scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool isPinned = false)
where T : IEquatable<T>
{
return new Tensor<T>(values, lengths, strides, isPinned);
}

/// <summary>
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
where T : IEquatable<T> => CreateUninitialized<T>(lengths, [], pinned);


/// <summary>
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
/// Creates a <see cref="Tensor{T}"/> and initializes it with the data from <paramref name="data"/>.
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false )
where T : IEquatable<T>
/// <param name="data">A <see cref="IEnumerable{T}"/> with the data to use for the initialization.</param>
/// <param name="lengths"></param>
public static Tensor<T> Create<T>(IEnumerable<T> data, scoped ReadOnlySpan<nint> lengths)
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
return new Tensor<T>(values, lengths, strides, pinned);
T[] values = data.ToArray();
return new Tensor<T>(values, lengths.IsEmpty ? [values.Length] : lengths, false);
}

/// <summary>
/// Creates a <see cref="Tensor{T}"/> and initializes it with the data from <paramref name="data"/>.
/// </summary>
/// <param name="data">A <see cref="IEnumerable{T}"/> with the data to use for the initialization.</param>
public static Tensor<T> CreateFromEnumerable<T>(IEnumerable<T> data)
where T : IEquatable<T>, IEqualityOperators<T, T, bool>
/// <param name="lengths"></param>
/// <param name="strides"></param>
/// <param name="isPinned"></param>
public static Tensor<T> Create<T>(IEnumerable<T> data, scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool isPinned = false)
{
T[] values = data.ToArray();
return new Tensor<T>(values, [values.Length], false);
return new Tensor<T>(values, lengths.IsEmpty ? [values.Length] : lengths, strides, isPinned);
}

/// <summary>
/// Creates a <see cref="Tensor{T}"/> and initializes it with random data uniformly distributed.
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
public static Tensor<T> CreateAndFillUniformDistribution<T>(params scoped ReadOnlySpan<nint> lengths)
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
where T : IFloatingPoint<T>
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = new T[linearLength];
Expand All @@ -121,16 +109,16 @@ public static Tensor<T> CreateAndFillUniformDistribution<T>(params scoped ReadOn
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
public static Tensor<T> CreateAndFillGaussianNormalDistribution<T>(params scoped ReadOnlySpan<nint> lengths)
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
where T : IFloatingPoint<T>
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = new T[linearLength];
GaussianDistribution(ref values, linearLength);
GaussianDistribution<T>(values, linearLength);
return new Tensor<T>(values, lengths, false);
}

private static void GaussianDistribution<T>(ref T[] values, nint linearLength)
where T : IEquatable<T>, IEqualityOperators<T, T, bool>, IFloatingPoint<T>
private static void GaussianDistribution<T>(in Span<T> values, nint linearLength)
where T : IFloatingPoint<T>
{
Random rand = Random.Shared;
for (int i = 0; i < linearLength; i++)
Expand All @@ -141,5 +129,45 @@ private static void GaussianDistribution<T>(ref T[] values, nint linearLength)
}
}
#endregion

/// <summary>
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, bool pinned = false)
=> CreateUninitialized<T>(lengths, [], pinned);

/// <summary>
/// Creates a <see cref="Tensor{T}"/> and does not initialize it. If <paramref name="pinned"/> is true, the memory will be pinned.
/// </summary>
/// <param name="lengths">A <see cref="ReadOnlySpan{T}"/> indicating the lengths of each dimension.</param>
/// <param name="strides">A <see cref="ReadOnlySpan{T}"/> indicating the strides of each dimension.</param>
/// <param name="pinned">A <see cref="bool"/> whether the underlying data should be pinned or not.</param>
public static Tensor<T> CreateUninitialized<T>(scoped ReadOnlySpan<nint> lengths, scoped ReadOnlySpan<nint> strides, bool pinned = false)
{
nint linearLength = TensorSpanHelpers.CalculateTotalLength(lengths);
T[] values = GC.AllocateUninitializedArray<T>((int)linearLength, pinned);
return new Tensor<T>(values, lengths, strides, pinned);
}

public static ref readonly TensorSpan<T> FillGaussianNormalDistribution<T>(in TensorSpan<T> destination) where T : IFloatingPoint<T>
{
Span<T> span = MemoryMarshal.CreateSpan<T>(ref destination._reference, (int)destination._flattenedLength);

GaussianDistribution<T>(span, destination._flattenedLength);

return ref destination;
}

public static ref readonly TensorSpan<T> FillUniformDistribution<T>(in TensorSpan<T> destination) where T : IFloatingPoint<T>
{
Span<T> span = MemoryMarshal.CreateSpan<T>(ref destination._reference, (int)destination._flattenedLength);

for (int i = 0; i < span.Length; i++)
span[i] = T.CreateChecked(Random.Shared.NextDouble());

return ref destination;
}
}
}
Loading

0 comments on commit 88013cb

Please sign in to comment.