Browse Source

drop slow Clamp() implementation

af/merge-core
Anton Firszov 7 years ago
parent
commit
813e743abc
  1. 3
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  2. 6
      src/ImageSharp/Common/Helpers/SimdUtils.cs
  3. 70
      tests/ImageSharp.Benchmarks/General/BasicMath/ClampFloat.cs
  4. 2
      tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs
  5. 2
      tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs

3
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -61,9 +61,6 @@ namespace SixLabors.ImageSharp
return x & (m - 1);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static float Clamp(float x, float min, float max) => Math.Min(max, Math.Max(min, x));
/// <summary>
/// Returns the absolute value of a 32-bit signed integer. Uses bit shifting to speed up the operation.
/// </summary>

6
src/ImageSharp/Common/Helpers/SimdUtils.cs

@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(InliningOptions.ShortMethod)]
internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> dest)
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same size!");
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
#if NETCOREAPP2_1
ExtendedIntrinsics.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest);
@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(InliningOptions.ShortMethod)]
internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan<float> source, Span<byte> dest)
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same size!");
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
#if NETCOREAPP2_1
ExtendedIntrinsics.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest);
@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp
}
[MethodImpl(InliningOptions.ShortMethod)]
private static byte ConvertToByte(float f) => (byte)ImageMaths.Clamp((f * 255f) + 0.5f, 0, 255f);
private static byte ConvertToByte(float f) => (byte)ComparableExtensions.Clamp((f * 255f) + 0.5f, 0, 255f);
[Conditional("DEBUG")]
private static void VerifyIsAvx2Compatible(string operation)

70
tests/ImageSharp.Benchmarks/General/BasicMath/ClampFloat.cs

@ -0,0 +1,70 @@
using System;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
{
public class ClampFloat
{
private readonly float min = -1.5f;
private readonly float max = 2.5f;
private static readonly float[] Values = { -10, -5, -3, -1.5f, -0.5f, 0f, 1f, 1.5f, 2.5f, 3, 10 };
[Benchmark(Baseline = true)]
public float UsingMathF()
{
float acc = 0;
for (int i = 0; i < Values.Length; i++)
{
acc += ClampUsingMathF(Values[i], this.min, this.max);
}
return acc;
}
[Benchmark]
public float UsingBranching()
{
float acc = 0;
for (int i = 0; i < Values.Length; i++)
{
acc += ClampUsingBranching(Values[i], this.min, this.max);
}
return acc;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float ClampUsingMathF(float x, float min, float max)
{
return Math.Min(max, Math.Max(min, x));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float ClampUsingBranching(float x, float min, float max)
{
if (x >= max)
{
return max;
}
if (x <= min)
{
return min;
}
return x;
}
// RESULTS:
// Method | Mean | Error | StdDev | Scaled |
// --------------- |---------:|----------:|----------:|-------:|
// UsingMathF | 30.37 ns | 0.3764 ns | 0.3337 ns | 1.00 |
// UsingBranching | 18.66 ns | 0.1043 ns | 0.0871 ns | 0.61 |
}
}

2
tests/ImageSharp.Benchmarks/General/BasicMath/Clamp.cs → tests/ImageSharp.Benchmarks/General/BasicMath/ClampInt32IntoByte.cs

@ -10,7 +10,7 @@ using BenchmarkDotNet.Attributes;
namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
{
public class Clamp
public class ClampInt32IntoByte
{
[Params(-1, 0, 255, 256)]
public int Value { get; set; }

2
tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs

@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers
[InlineData(10.1f, -0.1f, 10, 10f)]
public void Clamp(float x, float min, float max, float expected)
{
float actual = ImageMaths.Clamp(x, min, max);
float actual = x.Clamp(min, max);
Assert.Equal(expected, actual);
}

Loading…
Cancel
Save