Skip to content

Commit b6a3d2a

Browse files
authored
Merge pull request #85 from Sergio0694/feature_memory-4-5-1
System.Memory updated to 4.5.1
2 parents 0ca805e + 0d246d9 commit b6a3d2a

31 files changed

+160
-142
lines changed

NeuralNetwork.NET/APIs/DatasetLoader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
using NeuralNetworkNET.SupervisedLearning.Data;
1010
using NeuralNetworkNET.SupervisedLearning.Parameters;
1111
using NeuralNetworkNET.SupervisedLearning.Progress;
12-
using SixLabors.ImageSharp;
1312
using SixLabors.ImageSharp.PixelFormats;
13+
using SixLabors.ImageSharp.Processing;
1414

1515
namespace NeuralNetworkNET.APIs
1616
{

NeuralNetwork.NET/APIs/Datasets/Cifar10.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ private static unsafe void ExportSamples([NotNull] DirectoryInfo folder, (string
150150
int label = stream.ReadByte();
151151
stream.Read(temp, 0, SampleSize);
152152
using (Image<Rgb24> image = new Image<Rgb24>(32, 32))
153-
fixed (Rgb24* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
153+
fixed (Rgb24* p0 = image.GetPixelSpan())
154154
{
155155
for (int j = 0; j < ImageSize; j++)
156156
p0[j] = new Rgb24(ptemp[j], ptemp[j + ImageSize], ptemp[j + 2 * ImageSize]);

NeuralNetwork.NET/APIs/Datasets/Cifar100.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private static unsafe void ExportSamples([NotNull] DirectoryInfo folder, (string
188188
fine = stream.ReadByte();
189189
stream.Read(temp, 0, SampleSize);
190190
using (Image<Rgb24> image = new Image<Rgb24>(32, 32))
191-
fixed (Rgb24* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
191+
fixed (Rgb24* p0 = image.GetPixelSpan())
192192
{
193193
for (int j = 0; j < ImageSize; j++)
194194
p0[j] = new Rgb24(ptemp[j], ptemp[j + ImageSize], ptemp[j + 2 * ImageSize]);

NeuralNetwork.NET/APIs/Datasets/Mnist.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private static unsafe void ExportSamples([NotNull] DirectoryInfo folder, (string
172172
xGzip.Read(temp, 0, SampleSize);
173173
int label = yGzip.ReadByte();
174174
using (Image<Rgb24> image = new Image<Rgb24>(28, 28))
175-
fixed (Rgb24* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
175+
fixed (Rgb24* p0 = image.GetPixelSpan())
176176
{
177177
for (int j = 0; j < SampleSize; j++)
178178
p0[j] = new Rgb24(ptemp[j], ptemp[j], ptemp[j]);

NeuralNetwork.NET/APIs/Structs/DatasetSample.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ public readonly ref struct DatasetSample
1010
/// <summary>
1111
/// Gets the <see cref="Span{T}"/> referencing the current sample inputs
1212
/// </summary>
13-
public Span<float> X { get; }
13+
public ReadOnlySpan<float> X { get; }
1414

1515
/// <summary>
1616
/// Gets the <see cref="Span{T}"/> referencing the current sample expected outputs
1717
/// </summary>
18-
public Span<float> Y { get; }
18+
public ReadOnlySpan<float> Y { get; }
1919

20-
internal DatasetSample(Span<float> x, Span<float> y)
20+
internal DatasetSample(ReadOnlySpan<float> x, ReadOnlySpan<float> y)
2121
{
2222
X = x;
2323
Y = y;

NeuralNetwork.NET/APIs/Structs/Tensor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ public unsafe float[] ToArray(bool keepAlive = true)
281281
{
282282
if (Ptr == IntPtr.Zero) return new float[0, 0];
283283
float[,] result = new float[Entities, Length];
284-
new Span<float>(this, Size).CopyTo(result.AsSpan());
284+
fixed (float* p = result)
285+
new Span<float>(this, Size).CopyTo(new Span<float>(p, Size));
285286
if (!keepAlive) Free();
286287
return result;
287288
}

NeuralNetwork.NET/Extensions/ArrayExtensions.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,43 @@ namespace NeuralNetworkNET.Extensions
1111
/// </summary>
1212
internal static class ArrayExtensions
1313
{
14+
/// <summary>
15+
/// Flattens a 2D array to a 1D array
16+
/// </summary>
17+
/// <typeparam name="T">The type of each element in the input matrix</typeparam>
18+
/// <param name="m">The input 2D array to flatten</param>
19+
[Pure]
20+
[CollectionAccess(CollectionAccessType.Read)]
21+
public static unsafe T[] Flatten<T>([NotNull] this T[,] m) where T : unmanaged
22+
{
23+
fixed (T* p = m) return new Span<T>(p, m.Length).ToArray();
24+
}
25+
1426
/// <summary>
1527
/// Merges the line pairs in the input collection into two 2D arrays
1628
/// </summary>
1729
/// <typeparam name="T">The type of each element in the input lines</typeparam>
1830
/// <param name="lines">The lines to merge</param>
1931
[Pure]
2032
[CollectionAccess(CollectionAccessType.Read)]
21-
public static (T[,], T[,]) MergeLines<T>(this IEnumerable<(T[], T[])> lines) where T : struct
33+
public static unsafe (T[,], T[,]) MergeLines<T>(this IEnumerable<(T[], T[])> lines) where T : unmanaged
2234
{
2335
(T[] X, T[] Y)[] set = lines.ToArray();
2436
T[,]
2537
x = new T[set.Length, set[0].X.Length],
2638
y = new T[set.Length, set[0].Y.Length];
27-
Parallel.For(0, set.Length, i =>
39+
int
40+
wx = x.GetLength(1),
41+
wy = y.GetLength(1);
42+
fixed (T* px0 = x, py0 = y)
2843
{
29-
set[i].X.AsSpan().CopyTo(x.Slice(i));
30-
set[i].Y.AsSpan().CopyTo(y.Slice(i));
31-
}).AssertCompleted();
44+
T* px = px0, py = py0;
45+
Parallel.For(0, set.Length, i =>
46+
{
47+
set[i].X.AsSpan().CopyTo(new Span<T>(px + i * wx, wx));
48+
set[i].Y.AsSpan().CopyTo(new Span<T>(py + i * wy, wy));
49+
}).AssertCompleted();
50+
}
3251
return (x, y);
3352
}
3453
}

NeuralNetwork.NET/Extensions/DebugExtensions.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal static class DebugExtensions
1919
public static unsafe bool ContentEquals(this Span<float> x1, Span<float> x2, float absolute = 1e-6f, float relative = 1e-6f)
2020
{
2121
if (x1.Length != x2.Length) return false;
22-
fixed (float* p1 = &x1.DangerousGetPinnableReference(), p2 = &x2.DangerousGetPinnableReference())
22+
fixed (float* p1 = x1, p2 = x2)
2323
{
2424
for (int i = 0; i < x1.Length; i++)
2525
if (!p1[i].EqualsWithDelta(p2[i], absolute, relative))
@@ -55,13 +55,14 @@ public static bool ContentEquals(in this Tensor m, in Tensor o, float absolute =
5555
/// <param name="o">The second matrix to test</param>
5656
/// <param name="absolute">The relative comparison threshold</param>
5757
/// <param name="relative">The relative comparison threshold</param>
58-
public static bool ContentEquals([CanBeNull] this float[,] m, [CanBeNull] float[,] o, float absolute = 1e-6f, float relative = 1e-6f)
58+
public static unsafe bool ContentEquals([CanBeNull] this float[,] m, [CanBeNull] float[,] o, float absolute = 1e-6f, float relative = 1e-6f)
5959
{
6060
if (m == null && o == null) return true;
6161
if (m == null || o == null) return false;
6262
if (m.GetLength(0) != o.GetLength(0) ||
6363
m.GetLength(1) != o.GetLength(1)) return false;
64-
return m.AsSpan().ContentEquals(o.AsSpan(), absolute, relative);
64+
fixed (float* pm = m, po = o)
65+
return new Span<float>(pm, m.Length).ContentEquals(new Span<float>(po, o.Length), absolute, relative);
6566
}
6667

6768
/// <summary>

NeuralNetwork.NET/Extensions/SpanExtensions.cs

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Runtime.CompilerServices;
32
using System.Threading.Tasks;
43
using JetBrains.Annotations;
54

@@ -17,29 +16,27 @@ public static class SpanExtensions
1716
/// </summary>
1817
/// <param name="span">The <see cref="Span{T}"/> to fill up</param>
1918
/// <param name="provider">The values provider to use</param>
20-
public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider) where T : struct
19+
public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider) where T : unmanaged
2120
{
2221
// Fill in parallel
2322
int
2423
cores = Environment.ProcessorCount,
2524
batch = span.Length / cores,
26-
mod = span.Length % cores,
27-
size = Unsafe.SizeOf<T>();
28-
ref T r0 = ref span.DangerousGetPinnableReference();
29-
fixed (byte* p0 = &Unsafe.As<T, byte>(ref r0))
25+
mod = span.Length % cores;
26+
fixed (T* p0 = span)
3027
{
31-
byte* pc = p0;
28+
T* pc = p0;
3229
Parallel.For(0, cores, i =>
3330
{
34-
byte* p = pc + i * batch * size;
35-
for (int j = 0; j < batch; j++, p += size)
36-
Unsafe.Write(p, provider());
31+
T* p = pc + i * batch;
32+
for (int j = 0; j < batch; j++)
33+
p[j] = provider();
3734
}).AssertCompleted();
3835

3936
// Remaining values
4037
if (mod < 1) return;
4138
for (int i = span.Length - mod; i < span.Length; i++)
42-
Unsafe.Write(pc + i * size, provider());
39+
pc[i] = provider();
4340
}
4441
}
4542

@@ -51,11 +48,12 @@ public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider)
5148
/// <param name="w">The number of matrix columns</param>
5249
[Pure, NotNull]
5350
[CollectionAccess(CollectionAccessType.Read)]
54-
public static T[,] AsMatrix<T>(this Span<T> span, int h, int w) where T : struct
51+
public static unsafe T[,] AsMatrix<T>(this Span<T> span, int h, int w) where T : unmanaged
5552
{
5653
if (h * w != span.Length) throw new ArgumentException("The input dimensions don't match the source vector size");
5754
T[,] m = new T[h, w];
58-
span.CopyTo(m.AsSpan());
55+
fixed (void* p = m)
56+
span.CopyTo(new Span<T>(p, m.Length));
5957
return m;
6058
}
6159

@@ -65,55 +63,32 @@ public static unsafe void Fill<T>(this Span<T> span, [NotNull] Func<T> provider)
6563
/// <typeparam name="T">The type of each value in the input <see cref="Span{T}"/></typeparam>
6664
/// <param name="span">The input <see cref="Span{T}"/> to read</param>
6765
[Pure]
68-
public static unsafe int GetContentHashCode<T>(this Span<T> span) where T : struct
66+
public static unsafe int GetContentHashCode<T>(this Span<T> span) where T : unmanaged
6967
{
70-
fixed (byte* p0 = &Unsafe.As<T, byte>(ref span.DangerousGetPinnableReference()))
68+
fixed (T* p0 = span)
7169
{
72-
int size = Unsafe.SizeOf<T>();
7370
int hash = 17;
7471
unchecked
7572
{
7673
for (int i = 0; i < span.Length; i++)
77-
hash = hash * 23 + Unsafe.Read<T>(p0 + size * i).GetHashCode();
74+
hash = hash * 23 + p0[i].GetHashCode();
7875
return hash;
7976
}
8077
}
8178
}
8279

83-
/// <summary>
84-
/// Returns a deep copy of the input <see cref="Span{T}"/>
85-
/// </summary>
86-
/// <param name="span">The <see cref="Span{T}"/> to clone</param>
87-
/// <remarks>This method avoids the boxing of the <see cref="Array.Clone"/> method, and it is faster thanks to the use of the methods in the <see cref="Buffer"/> class</remarks>
88-
[Pure]
89-
[CollectionAccess(CollectionAccessType.Read)]
90-
public static T[] Copy<T>(this Span<T> span) where T : struct
91-
{
92-
T[] result = new T[span.Length];
93-
span.CopyTo(result);
94-
return result;
95-
}
96-
97-
/// <summary>
98-
/// Returns a new <see cref="Span{T}"/> instance from the input matrix
99-
/// </summary>
100-
/// <typeparam name="T">The type of the input matrix</typeparam>
101-
/// <param name="m">The input matrix</param>
102-
[Pure]
103-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
104-
public static Span<T> AsSpan<T>([NotNull] this T[,] m) where T : struct => Span<T>.DangerousCreate(m, ref m[0, 0], m.Length);
105-
10680
/// <summary>
10781
/// Extracts a single row from a given matrix
10882
/// </summary>
10983
/// <param name="m">The source matrix</param>
11084
/// <param name="row">The target row to return</param>
111-
[Pure]
85+
[Pure, NotNull]
11286
[CollectionAccess(CollectionAccessType.Read)]
113-
public static Span<T> Slice<T>([NotNull] this T[,] m, int row) where T : struct
87+
public static unsafe T[] Slice<T>([NotNull] this T[,] m, int row) where T : unmanaged
11488
{
11589
if (row < 0 || row > m.GetLength(0) - 1) throw new ArgumentOutOfRangeException(nameof(row), "The row index isn't valid");
116-
return Span<T>.DangerousCreate(m, ref m[row, 0], m.GetLength(1));
90+
int wm = m.GetLength(1);
91+
fixed (T* p = m) return new Span<T>(p + row * wm, wm).ToArray();
11792
}
11893

11994
#endregion
@@ -131,7 +106,7 @@ public static unsafe int Argmax(this Span<float> span)
131106
if (span.Length < 2) return default;
132107
int index = 0;
133108
float max = float.MinValue;
134-
fixed (float* p = &span.DangerousGetPinnableReference())
109+
fixed (float* p = span)
135110
{
136111
for (int j = 0; j < span.Length; j++)
137112
{
@@ -158,7 +133,7 @@ public static unsafe int Argmax(this Span<float> span)
158133
internal static unsafe bool MatchElementwiseThreshold(this Span<float> x1, Span<float> x2, float threshold)
159134
{
160135
if (x1.Length != x2.Length) throw new ArgumentException("The two input spans must have the same length");
161-
fixed (float* px1 = &x1.DangerousGetPinnableReference(), px2 = &x2.DangerousGetPinnableReference())
136+
fixed (float* px1 = x1, px2 = x2)
162137
for (int i = 0; i < x1.Length; i++)
163138
if (px1[i] > threshold != px2[i] > threshold)
164139
return false;
@@ -177,7 +152,7 @@ internal static unsafe bool MatchElementwiseThreshold(this Span<float> x1, Span<
177152
internal static unsafe bool IsCloseTo(this Span<float> x1, Span<float> x2, float threshold)
178153
{
179154
if (x1.Length != x2.Length) throw new ArgumentException("The two input spans must have the same length");
180-
fixed (float* px1 = &x1.DangerousGetPinnableReference(), px2 = &x2.DangerousGetPinnableReference())
155+
fixed (float* px1 = x1, px2 = x2)
181156
for (int i = 0; i < x1.Length; i++)
182157
if ((px1[i] - px2[i]).Abs() > threshold)
183158
return false;

NeuralNetwork.NET/Extensions/StreamExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal static class StreamExtensions
1616
/// <typeparam name="T">The <see langword="struct"/> type to serialize</typeparam>
1717
/// <param name="stream">The target <see cref="Stream"/> to use to write the data</param>
1818
/// <param name="value">The <see langword="struct"/> to write to the <see cref="Stream"/> instance</param>
19-
public static unsafe void Write<T>([NotNull] this Stream stream, T value) where T : struct
19+
public static unsafe void Write<T>([NotNull] this Stream stream, T value) where T : unmanaged
2020
{
2121
byte[] bytes = new byte[Unsafe.SizeOf<T>()];
2222
fixed (void* p = bytes) Unsafe.Copy(p, ref value);
@@ -30,7 +30,7 @@ public static unsafe void Write<T>([NotNull] this Stream stream, T value) where
3030
/// <param name="stream">The source <see cref="Stream"/> instance to use to read the data</param>
3131
/// <param name="value">The resulting <typeparamref name="T"/> value that is read from the <see cref="Stream"/></param>
3232
[MustUseReturnValue]
33-
public static unsafe bool TryRead<T>([NotNull] this Stream stream, out T value) where T : struct
33+
public static unsafe bool TryRead<T>([NotNull] this Stream stream, out T value) where T : unmanaged
3434
{
3535
byte[] bytes = new byte[Unsafe.SizeOf<T>()];
3636
value = default;

NeuralNetwork.NET/Helpers/ImageLoader.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using SixLabors.ImageSharp;
77
using SixLabors.ImageSharp.Advanced;
88
using SixLabors.ImageSharp.PixelFormats;
9+
using SixLabors.ImageSharp.Processing;
910

1011
namespace NeuralNetworkNET.Helpers
1112
{
@@ -42,7 +43,7 @@ private static unsafe float[] Load(Image<Argb32> image, ImageNormalizationMode n
4243
{
4344
int resolution = image.Height * image.Width;
4445
float[] sample = new float[resolution * 4];
45-
fixed (Argb32* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
46+
fixed (Argb32* p0 = image.GetPixelSpan())
4647
fixed (float* psample = sample)
4748
{
4849
for (int i = 0; i < resolution; i++)
@@ -63,7 +64,7 @@ private static unsafe float[] Load(Image<Rgba32> image, ImageNormalizationMode n
6364
{
6465
int resolution = image.Height * image.Width;
6566
float[] sample = new float[resolution * 4];
66-
fixed (Rgba32* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
67+
fixed (Rgba32* p0 = image.GetPixelSpan())
6768
fixed (float* psample = sample)
6869
{
6970
for (int i = 0; i < resolution; i++)
@@ -84,7 +85,7 @@ private static unsafe float[] Load(Image<Rgb24> image, ImageNormalizationMode no
8485
{
8586
int resolution = image.Height * image.Width;
8687
float[] sample = new float[resolution * 3];
87-
fixed (Rgb24* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
88+
fixed (Rgb24* p0 = image.GetPixelSpan())
8889
fixed (float* psample = sample)
8990
{
9091
for (int i = 0; i < resolution; i++)
@@ -104,7 +105,7 @@ private static unsafe float[] Load(Image<Alpha8> image, ImageNormalizationMode n
104105
{
105106
int resolution = image.Height * image.Width;
106107
float[] sample = new float[resolution];
107-
fixed (Alpha8* p0 = &image.DangerousGetPinnableReferenceToPixelBuffer())
108+
fixed (Alpha8* p0 = image.GetPixelSpan())
108109
fixed (float* psample = sample)
109110
for (int i = 0; i < resolution; i++)
110111
{

NeuralNetwork.NET/Helpers/Sha256.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public static class Sha256
2424
/// <param name="array">The input array to process</param>
2525
[PublicAPI]
2626
[Pure, NotNull]
27-
public static unsafe byte[] Hash<T>([NotNull] T[] array) where T : struct
27+
public static unsafe byte[] Hash<T>([NotNull] T[] array) where T : unmanaged
2828
{
2929
int size = Unsafe.SizeOf<T>() * array.Length;
30-
fixed (byte* p = &Unsafe.As<T, byte>(ref array[0]))
31-
using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(p, size, size, FileAccess.Read))
30+
fixed (T* p = array)
31+
using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream((byte*)p, size, size, FileAccess.Read))
3232
using (SHA256 provider = SHA256.Create())
3333
{
3434
return provider.ComputeHash(stream);
@@ -42,7 +42,7 @@ public static unsafe byte[] Hash<T>([NotNull] T[] array) where T : struct
4242
/// <param name="arrays">The arrays to process</param>
4343
[PublicAPI]
4444
[Pure, NotNull]
45-
public static unsafe byte[] Hash<T>([NotNull, ItemNotNull] params T[][] arrays) where T : struct
45+
public static unsafe byte[] Hash<T>([NotNull, ItemNotNull] params T[][] arrays) where T : unmanaged
4646
{
4747
// Compute the hashes in parallel
4848
if (arrays.Length == 0) return new byte[0];

NeuralNetwork.NET/Networks/Graph/Nodes/SumNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public CudaSumNode(ActivationType activation, [NotNull] [ItemNotNull] IReadOnlyL
121121
public override unsafe void Forward(Span<Tensor> inputs, out Tensor z, out Tensor a)
122122
{
123123
Descriptor.Set4D(DataType.FLOAT, TensorFormat.CUDNN_TENSOR_NCHW, inputs[0].Entities, inputs[0].Length, 1, 1);
124-
fixed (Tensor* p = &inputs.DangerousGetPinnableReference())
124+
fixed (Tensor* p = inputs)
125125
{
126126
Tensor.New(p->Entities, p->Length, out z);
127127
using (DeviceMemory<float> y_gpu = DnnInstance.Gpu.AllocateDevice(*p))

0 commit comments

Comments
 (0)