Skip to content

Commit 5d00a69

Browse files
committed
Added vector ops to FixedBuffer.
1 parent e7adca5 commit 5d00a69

File tree

5 files changed

+115
-14
lines changed

5 files changed

+115
-14
lines changed

jemalloc.Api/FixedBuffer.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Buffers;
33
using System.Collections.Generic;
4+
using System.Numerics;
45
using System.Runtime.CompilerServices;
56
using System.Runtime.InteropServices;
67
using System.Threading;
@@ -234,11 +235,80 @@ public bool EqualTo(T[] array)
234235
}
235236
}
236237

238+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
239+
public unsafe ReadOnlySpan<T> AcquireSpan()
240+
{
241+
Acquire();
242+
return new ReadOnlySpan<T>((void*) _Ptr, (int)Length);
243+
}
244+
245+
237246
public ReadOnlySpan<T> Slice(int start, int length)
238247
{
239248
return Span.Slice(start, length);
240249
}
241250

251+
public Vector<T> AcquireAsSingleVector()
252+
{
253+
if (this.Length != Vector<T>.Count)
254+
{
255+
throw new InvalidOperationException($"The length of the array must be {Vector<T>.Count} elements to create a vector of type {JemUtil.CLRType<T>().Name}.");
256+
}
257+
ReadOnlySpan<T> span = AcquireSpan();
258+
ReadOnlySpan<Vector<T>> vector = span.NonPortableCast<T, Vector<T>>();
259+
return vector[0];
260+
}
261+
262+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
263+
public unsafe ReadOnlySpan<Vector<T>> AcquireVectorSpan()
264+
{
265+
ThrowIfNotVectorizable();
266+
return AcquireSpan().NonPortableCast<T, Vector<T>>();
267+
}
268+
269+
#region Arithmetic
270+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
271+
public void VectorMultiply(T value)
272+
{
273+
ThrowIfNotVectorizable();
274+
T[] fill = new T[JemUtil.VectorLength<T>()];
275+
Span<T> fillSpan = new Span<T>(fill);
276+
fillSpan.Fill(value);
277+
Span<Vector<T>> vectorSpan = AcquireVectorWriteSpan();
278+
Vector<T> mulVector = fillSpan.NonPortableCast<T, Vector<T>>()[0];
279+
for (int i = 0; i < vectorSpan.Length; i++)
280+
{
281+
vectorSpan[i] = Vector.Multiply(vectorSpan[i], mulVector);
282+
}
283+
Release();
284+
}
285+
286+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
287+
public void VectorSqrt()
288+
{
289+
ThrowIfNotVectorizable();
290+
Span<Vector<T>> vector = AcquireVectorWriteSpan();
291+
for (int i = 0; i < vector.Length; i++)
292+
{
293+
vector[i] = Vector.SquareRoot(vector[i]);
294+
}
295+
Release();
296+
}
297+
298+
#endregion
299+
300+
private unsafe Span<T> AcquireWriteSpan()
301+
{
302+
Acquire();
303+
return new Span<T>((void*)_Ptr, (int)Length);
304+
}
305+
306+
public unsafe Span<Vector<T>> AcquireVectorWriteSpan()
307+
{
308+
ThrowIfNotVectorizable();
309+
return AcquireWriteSpan().NonPortableCast<T, Vector<T>>();
310+
}
311+
242312
[MethodImpl(MethodImplOptions.AggressiveInlining)]
243313
private unsafe ref T Read(int index)
244314
{
@@ -304,6 +374,14 @@ internal void ThrowIfTypeNotPrimitive()
304374
}
305375
}
306376

377+
internal void ThrowIfNotVectorizable()
378+
{
379+
if (Length == 0 || Length % JemUtil.VectorLength<T>() != 0)
380+
{
381+
throw new InvalidOperationException("Buffer is not vectorizable.");
382+
}
383+
}
384+
307385
internal string Name => $"{nameof(FixedBuffer<T>)}({this._Length})";
308386

309387
#endregion

jemalloc.Api/JemUtil.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Collections.Concurrent;
55
using System.Collections.Immutable;
6+
using System.Numerics;
67
using System.Runtime.CompilerServices;
78

89
namespace jemalloc
@@ -86,6 +87,16 @@ public static long ProcessPagedMemory
8687
return CurrentProcess.PagedMemorySize64;
8788
}
8889
}
90+
91+
public static Type CLRType<T>() => typeof(T);
92+
93+
public static uint ElementSizeInBytes<T>() where T: struct => (uint)JemUtil.SizeOfStruct<T>();
94+
95+
public static bool IsNumeric<T>() => JemUtil.IsNumericType<T>();
96+
97+
public static int VectorLength<T>() where T : struct => IsNumeric<T>() ? Vector<T>.Count : 0;
98+
99+
public static bool SIMD => Vector.IsHardwareAccelerated;
89100
#endregion
90101

91102
#region Methods

jemalloc.Benchmarks/Benchmarks/FixedBufferVsManagedArray.cs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ public void ArithmeticMutiplyManagedArray()
138138
{
139139
m[i] = GM<T>.Multiply(m[i], mul);
140140
}
141+
this.SetStatistic($"{nameof(ArithmeticMutiplyManagedArray)}_PrivateMemory", JemUtil.PrintBytes(JemUtil.ProcessPrivateMemory));
141142
}
142143

143144
[Benchmark(Description = "Vector multiply all values of a native array with a single value.")]
@@ -146,33 +147,40 @@ public void ArithmeticMultiplyNativeArray()
146147
{
147148
T mul = GetValue<T>("mul");
148149
T fill = GetValue<T>("fill");
149-
SafeArray<T> array = GetValue<SafeArray<T>>("nativeArray");
150+
FixedBuffer<T> array = GetValue<FixedBuffer<T>>("nativeArray");
150151
array.Fill(fill);
151-
array.VectorMultiply(mul);
152+
array.VectorMultiply(mul);
153+
this.SetStatistic($"{nameof(ArithmeticMultiplyNativeArray)}_PrivateMemory", JemUtil.PrintBytes(JemUtil.ProcessPrivateMemory));
152154
}
153155

154156
[GlobalCleanup(Target = nameof(ArithmeticMultiplyNativeArray))]
155-
public void ArithmeticMultiplyCleanup()
157+
public void ArithmeticMultiplyValidateAndCleanup()
156158
{
157159
InfoThis();
158-
int index = GM<T>.Rng.Next(0, ArraySize);
159-
SafeArray<T> nativeArray = GetValue<SafeArray<T>>("nativeArray");
160+
int index;
161+
FixedBuffer<T> nativeArray = GetValue<FixedBuffer<T>>("nativeArray");
160162
T[] managedArray = GetValue<T[]>("managedArray");
161163
T mul = GetValue<T>("mul");
162164
T fill = GetValue<T>("fill");
163165
T val = GM<T>.Multiply(fill, mul);
164-
if (!nativeArray[index].Equals(val))
165-
{
166-
Log.WriteLineError($"Native array at index {index} is {nativeArray[index]} not {val}.");
167-
throw new Exception();
168-
}
169-
else if (!managedArray[index].Equals(val))
166+
for (int i = 0; i < ArraySize % 100; i++)
170167
{
171-
Log.WriteLineError($"Managed array at index {index} is {managedArray[index]} not {val}.");
172-
throw new Exception();
168+
index = GM<T>.Rng.Next(0, ArraySize);
169+
if (!nativeArray[index].Equals(val))
170+
{
171+
Log.WriteLineError($"Native array at index {index} is {nativeArray[index]} not {val}.");
172+
throw new Exception();
173+
}
174+
else if (!managedArray[index].Equals(val))
175+
{
176+
Log.WriteLineError($"Managed array at index {index} is {managedArray[index]} not {val}.");
177+
throw new Exception();
178+
}
179+
173180
}
174181
managedArray = null;
175182
nativeArray.Release();
183+
nativeArray.Free();
176184
RemoveValue("managedArray");
177185
RemoveValue("nativeArray");
178186
RemoveValue("fill");

jemalloc.Benchmarks/Benchmarks/MallocVsArray.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class MallocVsArrayBenchmark<T> : JemBenchmark<T, int> where T : struct,
2020
public override void GlobalSetup()
2121
{
2222
base.GlobalSetup();
23-
Jem.Init("dirty_decay_ms:0,muzzy_decay_ms:0,junk:false");
23+
//Jem.Init("dirty_decay_ms:0,muzzy_decay_ms:0,junk:false");
2424
}
2525

2626
#region Create

jemalloc.Cli/jemalloc.Cli.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
<AssemblyVersion>0.2.0.0</AssemblyVersion>
99
<FileVersion>0.2.0.0</FileVersion>
1010
<Version>0.2.0-alpha</Version>
11+
<Authors>Allister Beharry</Authors>
12+
<Company />
13+
<Product>jemalloc.NET</Product>
14+
<PackageId>jemalloc CLI</PackageId>
1115
</PropertyGroup>
1216

1317
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

0 commit comments

Comments
 (0)