Browse Source

IsAvx2CompatibleArchitecture => HasVector8

pull/1143/head
Anton Firszov 6 years ago
parent
commit
cc056a695b
  1. 8
      src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
  2. 9
      src/ImageSharp/Common/Helpers/SimdUtils.cs
  3. 6
      src/ImageSharp/Common/Tuples/Vector4Pair.cs
  4. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
  5. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
  6. 8
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  7. 16
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs
  8. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs
  9. 2
      src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
  10. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs
  11. 2
      tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
  12. 4
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
  13. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
  14. 6
      tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs
  15. 2
      tests/ImageSharp.Tests/ProfilingBenchmarks/ResizeProfilingBenchmarks.cs

8
src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs

@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
public static class BasicIntrinsics256 public static class BasicIntrinsics256
{ {
public static bool IsAvailable { get; } = IsAvx2CompatibleArchitecture; public static bool IsAvailable { get; } = HasVector8;
#if !SUPPORTS_EXTENDED_INTRINSICS #if !SUPPORTS_EXTENDED_INTRINSICS
/// <summary> /// <summary>
@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> dest) internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> dest)
{ {
VerifyIsAvx2Compatible(nameof(BulkConvertByteToNormalizedFloat)); VerifyHasVector8(nameof(BulkConvertByteToNormalizedFloat));
VerifySpanInput(source, dest, 8); VerifySpanInput(source, dest, 8);
var bVec = new Vector<float>(256.0f / 255.0f); var bVec = new Vector<float>(256.0f / 255.0f);
@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan<float> source, Span<byte> dest) internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan<float> source, Span<byte> dest)
{ {
VerifyIsAvx2Compatible(nameof(BulkConvertNormalizedFloatToByteClampOverflows)); VerifyHasVector8(nameof(BulkConvertNormalizedFloatToByteClampOverflows));
VerifySpanInput(source, dest, 8); VerifySpanInput(source, dest, 8);
if (source.Length == 0) if (source.Length == 0)
@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan<float> source, Span<byte> dest) internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan<float> source, Span<byte> dest)
{ {
VerifyIsAvx2Compatible(nameof(BulkConvertNormalizedFloatToByte)); VerifyHasVector8(nameof(BulkConvertNormalizedFloatToByte));
VerifySpanInput(source, dest, 8); VerifySpanInput(source, dest, 8);
if (source.Length == 0) if (source.Length == 0)

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

@ -15,9 +15,10 @@ namespace SixLabors.ImageSharp
internal static partial class SimdUtils internal static partial class SimdUtils
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether the code is being executed on AVX2 CPU where both float and integer registers are of size 256 byte. /// Gets a value indicating whether <see cref="Vector{T}"/> code is being JIT-ed to AVX2 instructions
/// where both float and integer registers are of size 256 byte.
/// </summary> /// </summary>
public static bool IsAvx2CompatibleArchitecture { get; } = public static bool HasVector8 { get; } =
Vector.IsHardwareAccelerated && Vector<float>.Count == 8 && Vector<int>.Count == 8; Vector.IsHardwareAccelerated && Vector<float>.Count == 8 && Vector<int>.Count == 8;
/// <summary> /// <summary>
@ -151,9 +152,9 @@ namespace SixLabors.ImageSharp
private static byte ConvertToByte(float f) => (byte)ComparableExtensions.Clamp((f * 255f) + 0.5f, 0, 255f); private static byte ConvertToByte(float f) => (byte)ComparableExtensions.Clamp((f * 255f) + 0.5f, 0, 255f);
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void VerifyIsAvx2Compatible(string operation) private static void VerifyHasVector8(string operation)
{ {
if (!IsAvx2CompatibleArchitecture) if (!HasVector8)
{ {
throw new NotSupportedException($"{operation} is supported only on AVX2 CPU!"); throw new NotSupportedException($"{operation} is supported only on AVX2 CPU!");
} }

6
src/ImageSharp/Common/Tuples/Vector4Pair.cs

@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Tuples
/// Downscale method, specific to Jpeg color conversion. Works only if Vector{float}.Count == 4! /// TODO: Move it somewhere else. /// Downscale method, specific to Jpeg color conversion. Works only if Vector{float}.Count == 4! /// TODO: Move it somewhere else.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void RoundAndDownscalePreAvx2(float downscaleFactor) internal void RoundAndDownscalePreVector8(float downscaleFactor)
{ {
ref Vector<float> a = ref Unsafe.As<Vector4, Vector<float>>(ref this.A); ref Vector<float> a = ref Unsafe.As<Vector4, Vector<float>>(ref this.A);
a = a.FastRound(); a = a.FastRound();
@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tuples
/// TODO: Move it somewhere else. /// TODO: Move it somewhere else.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void RoundAndDownscaleAvx2(float downscaleFactor) internal void RoundAndDownscaleVector8(float downscaleFactor)
{ {
ref Vector<float> self = ref Unsafe.As<Vector4Pair, Vector<float>>(ref this); ref Vector<float> self = ref Unsafe.As<Vector4Pair, Vector<float>>(ref this);
Vector<float> v = self; Vector<float> v = self;
@ -79,4 +79,4 @@ namespace SixLabors.ImageSharp.Tuples
return $"{nameof(Vector4Pair)}({this.A}, {this.B})"; return $"{nameof(Vector4Pair)}({this.A}, {this.B})";
} }
} }
} }

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs

@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step. /// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step.
/// </summary> /// </summary>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceAvx2(float maximum) public void NormalizeColorsAndRoundInplaceVector8(float maximum)
{ {
var off = new Vector<float>(MathF.Ceiling(maximum / 2)); var off = new Vector<float>(MathF.Ceiling(maximum / 2));
var max = new Vector<float>(maximum); var max = new Vector<float>(maximum);

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt

@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step. /// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step.
/// </summary> /// </summary>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceAvx2(float maximum) public void NormalizeColorsAndRoundInplaceVector8(float maximum)
{ {
var off = new Vector<float>(MathF.Ceiling(maximum / 2)); var off = new Vector<float>(MathF.Ceiling(maximum / 2));
var max = new Vector<float>(maximum); var max = new Vector<float>(maximum);

8
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -471,9 +471,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// </summary> /// </summary>
public void NormalizeColorsAndRoundInplace(float maximum) public void NormalizeColorsAndRoundInplace(float maximum)
{ {
if (SimdUtils.IsAvx2CompatibleArchitecture) if (SimdUtils.HasVector8)
{ {
this.NormalizeColorsAndRoundInplaceAvx2(maximum); this.NormalizeColorsAndRoundInplaceVector8(maximum);
} }
else else
{ {
@ -497,7 +497,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
public void LoadFrom(ref Block8x8 source) public void LoadFrom(ref Block8x8 source)
{ {
#if SUPPORTS_EXTENDED_INTRINSICS #if SUPPORTS_EXTENDED_INTRINSICS
if (SimdUtils.IsAvx2CompatibleArchitecture) if (SimdUtils.HasVector8)
{ {
this.LoadFromInt16ExtendedAvx2(ref source); this.LoadFromInt16ExtendedAvx2(ref source);
return; return;
@ -513,7 +513,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
public void LoadFromInt16ExtendedAvx2(ref Block8x8 source) public void LoadFromInt16ExtendedAvx2(ref Block8x8 source)
{ {
DebugGuard.IsTrue( DebugGuard.IsTrue(
SimdUtils.IsAvx2CompatibleArchitecture, SimdUtils.HasVector8,
"LoadFromUInt16ExtendedAvx2 only works on AVX2 compatible architecture!"); "LoadFromUInt16ExtendedAvx2 only works on AVX2 compatible architecture!");
ref Vector<short> sRef = ref Unsafe.As<Block8x8, Vector<short>>(ref source); ref Vector<short> sRef = ref Unsafe.As<Block8x8, Vector<short>>(ref source);

16
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs

@ -90,15 +90,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
if (Vector<float>.Count == 4) if (Vector<float>.Count == 4)
{ {
// TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector<T> is terrible?) // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector<T> is terrible?)
r.RoundAndDownscalePreAvx2(maxValue); r.RoundAndDownscalePreVector8(maxValue);
g.RoundAndDownscalePreAvx2(maxValue); g.RoundAndDownscalePreVector8(maxValue);
b.RoundAndDownscalePreAvx2(maxValue); b.RoundAndDownscalePreVector8(maxValue);
} }
else if (SimdUtils.IsAvx2CompatibleArchitecture) else if (SimdUtils.HasVector8)
{ {
r.RoundAndDownscaleAvx2(maxValue); r.RoundAndDownscaleVector8(maxValue);
g.RoundAndDownscaleAvx2(maxValue); g.RoundAndDownscaleVector8(maxValue);
b.RoundAndDownscaleAvx2(maxValue); b.RoundAndDownscaleVector8(maxValue);
} }
else else
{ {
@ -114,4 +114,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
} }
} }
} }
} }

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{ {
} }
public static bool IsAvailable => Vector.IsHardwareAccelerated && SimdUtils.IsAvx2CompatibleArchitecture; public static bool IsAvailable => Vector.IsHardwareAccelerated && SimdUtils.HasVector8;
public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result) public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
{ {

2
src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs

@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
return int.MaxValue; return int.MaxValue;
} }
return SimdUtils.ExtendedIntrinsics.IsAvailable && SimdUtils.IsAvx2CompatibleArchitecture ? 256 : 128; return SimdUtils.ExtendedIntrinsics.IsAvailable && SimdUtils.HasVector8 ? 256 : 128;
} }
} }
} }

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_CopyTo1x1.cs

@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations
[GlobalSetup] [GlobalSetup]
public void Setup() public void Setup()
{ {
if (!SimdUtils.IsAvx2CompatibleArchitecture) if (!SimdUtils.HasVector8)
{ {
throw new InvalidOperationException("Benchmark Block8x8F_CopyTo1x1 is invalid on platforms without AVX2 support."); throw new InvalidOperationException("Benchmark Block8x8F_CopyTo1x1 is invalid on platforms without AVX2 support.");
} }

2
tests/ImageSharp.Tests/Common/SimdUtilsTests.cs

@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests.Common
private bool SkipOnNonAvx2([CallerMemberName] string testCaseName = null) private bool SkipOnNonAvx2([CallerMemberName] string testCaseName = null)
{ {
if (!SimdUtils.IsAvx2CompatibleArchitecture) if (!SimdUtils.HasVector8)
{ {
this.Output.WriteLine("Skipping AVX2 specific test case: " + testCaseName); this.Output.WriteLine("Skipping AVX2 specific test case: " + testCaseName);
return true; return true;

4
tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
private bool SkipOnNonAvx2Runner() private bool SkipOnNonAvx2Runner()
{ {
if (!SimdUtils.IsAvx2CompatibleArchitecture) if (!SimdUtils.HasVector8)
{ {
this.Output.WriteLine("AVX2 not supported, skipping!"); this.Output.WriteLine("AVX2 not supported, skipping!");
return true; return true;
@ -257,7 +257,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
expected.RoundInplace(); expected.RoundInplace();
Block8x8F actual = source; Block8x8F actual = source;
actual.NormalizeColorsAndRoundInplaceAvx2(255); actual.NormalizeColorsAndRoundInplaceVector8(255);
this.Output.WriteLine(expected.ToString()); this.Output.WriteLine(expected.ToString());
this.Output.WriteLine(actual.ToString()); this.Output.WriteLine(actual.ToString());

2
tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[MemberData(nameof(CommonConversionData))] [MemberData(nameof(CommonConversionData))]
public void FromYCbCrSimdAvx2(int inputBufferLength, int resultBufferLength, int seed) public void FromYCbCrSimdAvx2(int inputBufferLength, int resultBufferLength, int seed)
{ {
if (!SimdUtils.IsAvx2CompatibleArchitecture) if (!SimdUtils.HasVector8)
{ {
this.Output.WriteLine("No AVX2 present, skipping test!"); this.Output.WriteLine("No AVX2 present, skipping test!");
return; return;

6
tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs

@ -30,12 +30,12 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
{ TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, 20 }, { TestImages.Jpeg.BenchmarkSuite.Jpeg400_SmallMonochrome, 20 },
{ TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, 20 }, { TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr, 20 },
{ TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr, 40 }, { TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr, 40 },
// TestImages.Jpeg.BenchmarkSuite.MissingFF00ProgressiveBedroom159_MidSize420YCbCr, // { TestImages.Jpeg.BenchmarkSuite.MissingFF00ProgressiveBedroom159_MidSize420YCbCr, 10 },
// TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr, // { TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr, 5 },
{ TestImages.Jpeg.BenchmarkSuite.ExifGetString750Transform_Huge420YCbCr, 5 } { TestImages.Jpeg.BenchmarkSuite.ExifGetString750Transform_Huge420YCbCr, 5 }
}; };
[Theory(Skip = ProfilingSetup.SkipProfilingTests)] [Theory]
[MemberData(nameof(DecodeJpegData))] [MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg(string fileName, int executionCount) public void DecodeJpeg(string fileName, int executionCount)
{ {

2
tests/ImageSharp.Tests/ProfilingBenchmarks/ResizeProfilingBenchmarks.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks
public int ExecutionCount { get; set; } = 50; public int ExecutionCount { get; set; } = 50;
[Theory(Skip = ProfilingSetup.SkipProfilingTests)] [Theory]
[InlineData(100, 100)] [InlineData(100, 100)]
[InlineData(2000, 2000)] [InlineData(2000, 2000)]
public void ResizeBicubic(int width, int height) public void ResizeBicubic(int width, int height)

Loading…
Cancel
Save