Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sn4k3/UVtools.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'UVtools.GUI/Forms/FrmBenchmark.cs')
-rw-r--r--UVtools.GUI/Forms/FrmBenchmark.cs444
1 files changed, 444 insertions, 0 deletions
diff --git a/UVtools.GUI/Forms/FrmBenchmark.cs b/UVtools.GUI/Forms/FrmBenchmark.cs
new file mode 100644
index 0000000..ca7a043
--- /dev/null
+++ b/UVtools.GUI/Forms/FrmBenchmark.cs
@@ -0,0 +1,444 @@
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Reflection;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Emgu.CV;
+using Emgu.CV.CvEnum;
+using UVtools.Core.Extensions;
+using UVtools.GUI.Controls;
+
+namespace UVtools.GUI.Forms
+{
+ public partial class FrmBenchmark : Form
+ {
+ private CancellationTokenSource TokenSource { get; set; }
+ private CancellationToken Token => TokenSource.Token;
+
+ private RNGCryptoServiceProvider RandomProvider { get; }
+
+ private const ushort SingleThreadTests = 100;
+ private const ushort MultiThreadTests = 1000;
+
+ public const string RunsAbbreviation = "TDPS";
+ public const string StressCPUTestName = "Stress CPU (Run until stop)";
+
+ public FrmBenchmark()
+ {
+ InitializeComponent();
+ lbDescription.Text += $"CPU: {BenchmarkTest.DEVCPU}\nRAM: {BenchmarkTest.DEVRAM}";
+ RandomProvider = new RNGCryptoServiceProvider();
+
+ cbTest.Items.AddRange(
+ new object[]
+ {
+ new BenchmarkTest("4K Random CBBDLP Enconde", "Test4KRandomCBBDLPEncode", 40.30f, 246.30f),
+ new BenchmarkTest("8K Random CBBDLP Enconde", "Test8KRandomCBBDLPEncode", 9.70f, 64.10f),
+ new BenchmarkTest("4K Random CBT Enconde", "Test4KRandomCBTEncode", 13.50f, 113.30f),
+ new BenchmarkTest("8K Random CBT Enconde", "Test8KRandomCBTEncode", 3.40f, 28.20f),
+ new BenchmarkTest("4K Random PW0 Enconde", "Test4KRandomPW0Encode", 14.10f, 89.00f),
+ new BenchmarkTest("8K Random PW0 Enconde", "Test8KRandomPW0Encode", 3.50f, 22.40f),
+ new BenchmarkTest(StressCPUTestName, "Test4KRandomCBTEncode", 0, 0),
+ }
+ );
+ cbTest.SelectedIndex = 0;
+ }
+
+ private void FrmBenchmark_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (!btnStart.Enabled)
+ e.Cancel = true;
+ }
+
+ private void EventClicked(object sender, EventArgs e)
+ {
+ if (ReferenceEquals(sender, btnStart))
+ {
+ StartBenchmark();
+ return;
+ }
+ if (ReferenceEquals(sender, btnStop))
+ {
+ TokenSource.Cancel();
+ return;
+ }
+ }
+
+ private void EventSelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (ReferenceEquals(sender, cbTest))
+ {
+ BenchmarkTest benchmark = cbTest.SelectedItem as BenchmarkTest;
+ lbSingleThreadDevResults.Text = $"Single Thread: {benchmark.DevSingleThreadResult} {RunsAbbreviation}";
+ lbMultiThreadDevResults.Text = $"Multi Thread: {benchmark.DevMultiThreadResult} {RunsAbbreviation}";
+ return;
+ }
+ }
+
+ private void StartBenchmark()
+ {
+ if (!btnStart.Enabled) return;
+ cbTest.Enabled =
+ btnStart.Enabled = false;
+ btnStop.Enabled = true;
+
+ TokenSource = new CancellationTokenSource();
+
+ progressBar.Style = ProgressBarStyle.Marquee;
+
+ BenchmarkTest benchmark = cbTest.SelectedItem as BenchmarkTest;
+ MethodInfo theMethod = GetType().GetMethod(benchmark.FunctionName);
+
+ if (!benchmark.Name.Equals(StressCPUTestName))
+ {
+ lbSingleThreadResults.Text = $"Single Thread: Running {SingleThreadTests} tests";
+ lbMultiThreadResults.Text = $"Multi Thread: Running {MultiThreadTests} tests";
+ }
+
+
+ Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ if (benchmark.Name.Equals(StressCPUTestName))
+ {
+ while (true)
+ {
+ if (Token.IsCancellationRequested) break;
+ Parallel.For(0, MultiThreadTests, i =>
+ {
+ if (Token.IsCancellationRequested) return;
+ theMethod.Invoke(this, null);
+ });
+ }
+
+ return;
+ }
+
+ Stopwatch sw = Stopwatch.StartNew();
+ for (int i = 0; i < SingleThreadTests; i++)
+ {
+ if(Token.IsCancellationRequested) Token.ThrowIfCancellationRequested();
+ theMethod.Invoke(this, null);
+ }
+
+ sw.Stop();
+ Invoke((MethodInvoker) delegate
+ {
+ // Running on the UI thread
+ UpdateResults(true, sw.ElapsedMilliseconds);
+ });
+
+ if (Token.IsCancellationRequested) Token.ThrowIfCancellationRequested();
+
+ sw.Restart();
+ Parallel.For(0, MultiThreadTests, i =>
+ {
+ if (Token.IsCancellationRequested) return;
+ theMethod.Invoke(this, null);
+ });
+
+ sw.Stop();
+
+ if (Token.IsCancellationRequested) Token.ThrowIfCancellationRequested();
+
+ Invoke((MethodInvoker)delegate
+ {
+ // Running on the UI thread
+ UpdateResults(false, sw.ElapsedMilliseconds);
+ });
+ }
+ catch (OperationCanceledException)
+ {
+
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ finally
+ {
+ Invoke((MethodInvoker)StopBenchmark);
+ }
+ }, Token);
+ }
+
+ private void StopBenchmark()
+ {
+ btnStart.Enabled = true;
+ btnStop.Enabled = false;
+ cbTest.Enabled = true;
+ progressBar.Style = ProgressBarStyle.Blocks;
+ }
+
+ public byte[] EncodeCbddlpImage(Mat image, byte bit = 0)
+ {
+ List<byte> rawData = new List<byte>();
+ var span = image.GetPixelSpan<byte>();
+
+ bool obit = false;
+ int rep = 0;
+
+ //ngrey:= uint16(r | g | b)
+ // thresholds:
+ // aa 1: 127
+ // aa 2: 255 127
+ // aa 4: 255 191 127 63
+ // aa 8: 255 223 191 159 127 95 63 31
+ byte threshold = (byte)(256 / 1 * bit - 1);
+
+ void AddRep()
+ {
+ if (rep <= 0) return;
+
+ byte by = (byte)rep;
+
+ if (obit)
+ {
+ by |= 0x80;
+ //bitsOn += uint(rep)
+ }
+
+ rawData.Add(by);
+ }
+
+ for (int pixel = 0; pixel < span.Length; pixel++)
+ {
+ var nbit = span[pixel] >= threshold;
+
+ if (nbit == obit)
+ {
+ rep++;
+
+ if (rep == 0x7d)
+ {
+ AddRep();
+ rep = 0;
+ }
+ }
+ else
+ {
+ AddRep();
+ obit = nbit;
+ rep = 1;
+ }
+ }
+
+ // Collect stragglers
+ AddRep();
+
+
+ return rawData.ToArray();
+ }
+
+ private byte[] EncodeCbtImage(Mat image)
+ {
+ List<byte> rawData = new List<byte>();
+ byte color = byte.MaxValue >> 1;
+ uint stride = 0;
+ var span = image.GetPixelSpan<byte>();
+
+ void AddRep()
+ {
+ if (stride == 0)
+ {
+ return;
+ }
+
+ if (stride > 1)
+ {
+ color |= 0x80;
+ }
+ rawData.Add(color);
+
+ if (stride <= 1)
+ {
+ // no run needed
+ return;
+ }
+
+ if (stride <= 0x7f)
+ {
+ rawData.Add((byte)stride);
+ return;
+ }
+
+ if (stride <= 0x3fff)
+ {
+ rawData.Add((byte)((stride >> 8) | 0x80));
+ rawData.Add((byte)stride);
+ return;
+ }
+
+ if (stride <= 0x1fffff)
+ {
+ rawData.Add((byte)((stride >> 16) | 0xc0));
+ rawData.Add((byte)(stride >> 8));
+ rawData.Add((byte)stride);
+ return;
+ }
+
+ if (stride <= 0xfffffff)
+ {
+ rawData.Add((byte)((stride >> 24) | 0xe0));
+ rawData.Add((byte)(stride >> 16));
+ rawData.Add((byte)(stride >> 8));
+ rawData.Add((byte)stride);
+ }
+
+ }
+
+
+ for (int pixel = 0; pixel < span.Length; pixel++)
+ {
+ var grey7 = (byte)(span[pixel] >> 1);
+
+ if (grey7 == color)
+ {
+ stride++;
+ }
+ else
+ {
+ AddRep();
+ color = grey7;
+ stride = 1;
+ }
+ }
+
+ AddRep();
+
+
+ return rawData.ToArray();
+ }
+
+ public byte[] EncodePW0Image(Mat image)
+ {
+ List<byte> rawData = new List<byte>();
+ var span = image.GetPixelSpan<byte>();
+
+ int lastColor = -1;
+ int reps = 0;
+
+ void PutReps()
+ {
+ while (reps > 0)
+ {
+ int done = reps;
+
+ if (lastColor == 0 || lastColor == 0xf)
+ {
+ if (done > 0xfff)
+ {
+ done = 0xfff;
+ }
+ //more:= []byte{ 0, 0}
+ //binary.BigEndian.PutUint16(more, uint16(done | (color << 12)))
+
+ //rle = append(rle, more...)
+
+ ushort more = (ushort)(done | (lastColor << 12));
+ rawData.Add((byte)(more >> 8));
+ rawData.Add((byte)more);
+ }
+ else
+ {
+ if (done > 0xf)
+ {
+ done = 0xf;
+ }
+ rawData.Add((byte)(done | lastColor << 4));
+ }
+
+ reps -= done;
+ }
+ }
+
+ for (int i = 0; i < span.Length; i++)
+ {
+ int color = span[i] >> 4;
+
+ if (color == lastColor)
+ {
+ reps++;
+ }
+ else
+ {
+ PutReps();
+ lastColor = color;
+ reps = 1;
+ }
+ }
+
+ PutReps();
+
+ return rawData.ToArray();
+ }
+
+ private void UpdateResults(bool isSingleThread, long milliseconds)
+ {
+ decimal seconds = Math.Round(milliseconds / 1000m, 2);
+ //var text = (isSingleThread ? "Single" : "Multi") + $" Thread: {Math.Round(SingleThreadTests / seconds, 2)} OPS ({seconds}s)";
+
+ if(isSingleThread)
+ lbSingleThreadResults.Text = $"Single Thread: {Math.Round(SingleThreadTests / seconds, 2)} {RunsAbbreviation} ({SingleThreadTests} tests / {seconds}s)";
+ else
+ lbMultiThreadResults.Text = $"Multi Thread: {Math.Round(MultiThreadTests / seconds, 2)} {RunsAbbreviation} ({MultiThreadTests} tests / {seconds}s)"; ;
+ }
+
+ #region Tests
+
+ public Mat RandomMat(int width, int height)
+ {
+ var bytes = new byte[width * height];
+ RandomProvider.GetBytes(bytes);
+ Mat mat = new Mat(new Size(width, height), DepthType.Cv8U, 1);
+ mat.SetBytes(bytes);
+ return mat;
+ }
+
+ public void Test4KRandomCBBDLPEncode()
+ {
+ using (var mat = RandomMat(3840, 2160))
+ EncodeCbddlpImage(mat);
+ }
+
+ public void Test8KRandomCBBDLPEncode()
+ {
+ using (var mat = RandomMat(7680, 4320))
+ EncodeCbddlpImage(mat);
+ }
+
+ public void Test4KRandomCBTEncode()
+ {
+ using (var mat = RandomMat(3840, 2160))
+ EncodeCbtImage(mat);
+ }
+
+ public void Test8KRandomCBTEncode()
+ {
+ using (var mat = RandomMat(7680, 4320))
+ EncodeCbtImage(mat);
+ }
+
+ public void Test4KRandomPW0Encode()
+ {
+ using (var mat = RandomMat(3840, 2160))
+ EncodePW0Image(mat);
+ }
+
+ public void Test8KRandomPW0Encode()
+ {
+ using (var mat = RandomMat(7680, 4320))
+ EncodePW0Image(mat);
+ }
+
+ #endregion
+
+
+ }
+}