Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add arm64 intrinsics for cmyk converter #2400

Merged

Conversation

stefannikolei
Copy link
Contributor

@stefannikolei stefannikolei commented Mar 13, 2023

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

Added Simd for CMYK. I added ARM64 because there was no matching method in arm32

Benchmarks:

Method Mean Error StdDev Ratio RatioSD
Scalar 288.7 ns 1.75 ns 1.64 ns 1.00 0.00
SimdVector8 125.4 ns 1.74 ns 1.63 ns 0.43 0.01
SimdVectorAvx NA NA NA ? ?
SimdVectorArm64 108.1 ns 0.56 ns 0.43 ns 0.37 0.00

@antonfirsov
Copy link
Member

antonfirsov commented Mar 14, 2023

The 1-2% differences reported by the test failures don't seem to be horrible, but @stefannikolei do you have an opportunity to check the output images visually just to be on the safe side?

Also, I would make sure the increased tolerance only applies to ARM, and only for the images where it's necessary. We can define conditional percentage values right in TheoryData definitions:

public static readonly TheoryData<JpegEncodingColor, int, float> CmykEncodingSetups = new()
{
{ JpegEncodingColor.Cmyk, 100, 0.0159f / 100 },
{ JpegEncodingColor.Cmyk, 80, 0.3922f / 100 },
{ JpegEncodingColor.Cmyk, 40, 0.6488f / 100 },
};

@stefannikolei
Copy link
Contributor Author

@antonfirsov For me the visual test failed. 😞
EncodeBaseline_Interleaved_Rgb24_cmyk_Cmyk-Q40
EncodeBaseline_NonInterleavedMode_Rgb24_cmyk_Cmyk-Q40

@br3aker
Copy link
Contributor

br3aker commented Mar 14, 2023

Don't have an ARM with me but I'll try to take a look on this today, looks like a clamping issue to me.

@stefannikolei
Copy link
Contributor Author

Don't have an ARM with me but I'll try to take a look on this today, looks like a clamping issue to me.

If you want I can give you temp access to my arm vm.

@antonfirsov
Copy link
Member

We should also check RGB conversion output from #2397.

@@ -20,7 +20,7 @@ public class JpegColorConverterTests

private const int TestBufferLength = 40;

private const HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX;
private const HwIntrinsics IntrinsicsConfig = HwIntrinsics.AllowAll | HwIntrinsics.DisableHWIntrinsic;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why don't these tests fail with JpegColorConverterArm64?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me too, we need to re-review the tests, they should fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah now I got you... The Encoder tests failed. And this should also fail...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefannikolei or @brianpopow since you have the VM - can you try injecting an exception into the CmykArm64 methods and running dotnet test -f net6.0 --filter FullyQualifiedName~JpegColorConverterTests? If it gets hit, there's probably a bug in the tests since it they didn't show the regression, if not, it's probably a bug in FeatureTestRunner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those failed:
ImageSharp\tests\ImageSharp.Tests\Formats\Jpg\JpegColorConverterTests.cs:line 81

But I also saw all xxxFromVector methods fail because it is not supported on the hardware(vm) --> The DebugGuard throws here because I ran the tests in Debug mode

Child exception:
  System.InvalidOperationException: YccKVector converter is not supported on current hardware.
   at SixLabors.DebugGuard.IsTrue(Boolean target, String message) in C:\Users\nikoleis\source\ImageSharp\src\ImageSharp\Common\Helpers\DebugGuard.cs:line 24
   at SixLabors.ImageSharp.Formats.Jpeg.Components.JpegColorConverterBase.JpegColorConverterVector.ConvertToRgbInplace(ComponentValues& values) in C:\Users\nikoleis\source\ImageSharp\src\ImageSharp\Formats\Jpeg\Components\ColorConverters\JpegColorConverterVector.cs:line 41
``

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@antonfirsov The FeatureTestRunner seems to work as expected. Some path of the intrinsics methods (ConvertFromRgb) were not covered by tests. That's why the error was not detected. I have added tests for those.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have decided to revert the IntrinsicsConfig back to HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2. I think it was a mistake to change it. The IntrinsicsConfig is only used by the Vector color conversion tests. On x64 disabling AVX2 makes sense to test SSE here.

This means on ARM the test will be run twice, once 'HwIntrinsics.AllowAlland onceHwIntrinsics.DisableAVX2'. I dont know howto change it so the second run will be avoided, but I also think its not a big deal. If anyone has a better idea let me know.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can use this lib https://github.com/AArnott/Xunit.SkippableFact and just skip the not supported runs.

So we can define the desired ones (avx/sse/arm) as a theory.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think its really worth the extra effort only to skip an addional test run on ARM. We maybe need to re-evaluate once we add more ARM code / tests.

@stefannikolei
Copy link
Contributor Author

stefannikolei commented Mar 14, 2023

We should also check RGB conversion output from #2397.

The RGB pictures look good to me
EncodeBaseline_Interleaved_Rgb24_CalliphoraPartial_Rgb-Q100
Filename: EncodeBaseline_Interleaved_Rgb24_CalliphoraPartial_Rgb-Q100

Vector128<float> ytmp = AdvSimd.Subtract(scale, Unsafe.Add(ref srcB, i));
Vector128<float> ktmp = AdvSimd.Min(ctmp, AdvSimd.Min(mtmp, ytmp));

Vector128<float> kMask = AdvSimd.CompareEqual(ktmp, scale);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AVX version has Avx.CompareNotEqual here, could that be the problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I will have a Look. Can not remember changing it while porting 🫣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried debugging the code on VS 2022 but it just hangs when I step to the next line :(

This line should not make any difference in my eyes. Because it is ConvertFromRgb. The code which we need to look into is ConvertToRgb? Or am I wrong?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConvertFromRgb is used during encoding from ImageSharp to actual jpeg image.
ConvertToRgb is used during decding from jpeg to ImageSharp.
Problem can be in any of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests work now :) Any chance to get the test output from the test run?

I changed it from Negate to Not. That makes sense :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefannikolei great that you found the problem.

Any chance to get the test output from the test run?

Unfortunately I think the artifacts of the test run are only uploaded when it fails. I will try to tests it on ARM tomorrow and see if the results look good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran the tests. The images look good now

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm, the image looks good now.

@brianpopow
Copy link
Collaborator

@stefannikolei I just tried to build your branch on my ARM device, but I am getting build errors. I pretty sure those build errors are not related to your changes. I am getting compiler error CS8170 in ColorMatrix.impl.cs.

I am using dotnet sdk 6.0.113 on ubuntu. What version are you using? Any idea howto fix this?

@stefannikolei
Copy link
Contributor Author

@stefannikolei I just tried to build your branch on my ARM device, but I am getting build errors. I pretty sure those build errors are not related to your changes. I am getting compiler error CS8170 in ColorMatrix.impl.cs.

I am using dotnet sdk 6.0.113 on ubuntu. What version are you using? Any idea howto fix this?

I am using 7.0.xxx that's why the dotnet6 arm builds/test is disabled. Cause the image only had dotnet6 and in dotnet6 sdk the implementation of colormatrix does not build.

This is discussed in the rgb PR

@JimBobSquarePants
Copy link
Member

We should update the readme to say we need the NET7 SDK

@JimBobSquarePants
Copy link
Member

I'm happy here if everyone else is.

@br3aker
Copy link
Contributor

br3aker commented Mar 20, 2023

Looks good!

Copy link
Member

@antonfirsov antonfirsov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good, thanks @brianpopow for cleaning up the tests!

Copy link
Collaborator

@brianpopow brianpopow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think, this good to be merged now.

@antonfirsov antonfirsov merged commit d7cd46f into SixLabors:main Mar 21, 2023
@stefannikolei stefannikolei deleted the stefannikolei/arm/colorConvertercmyk branch March 25, 2023 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants