private Measurement MultiInvoke <T>(IterationMode mode, int index, Action setupAction, Func <T> targetAction, Action cleanupAction, long invocationCount, long operationsPerInvoke, GarbageCollection garbageCollectionSettings, T returnHolder = default(T)) { var totalOperations = invocationCount * operationsPerInvoke; setupAction(); ClockSpan clockSpan; GcCollect(garbageCollectionSettings); if (invocationCount == 1) { var chronometer = Chronometer.Start(); returnHolder = targetAction(); clockSpan = chronometer.Stop(); } else if (invocationCount < int.MaxValue) { int intInvocationCount = (int)invocationCount; var chronometer = Chronometer.Start(); RunAction(targetAction, intInvocationCount); clockSpan = chronometer.Stop(); } else { var chronometer = Chronometer.Start(); RunAction(targetAction, invocationCount); clockSpan = chronometer.Stop(); } multiInvokeReturnHolder = returnHolder; var measurement = new Measurement(0, mode, index, totalOperations, clockSpan.GetNanoseconds()); Console.WriteLine(measurement.ToOutputLine()); GcCollect(garbageCollectionSettings); return(measurement); }
public void Update() { //switch iteration mode if (Input.GetKeyDown(KeyCode.LeftBracket)) { selectedAlgorithm = ((int)selectedAlgorithm) == aMin ? (Algorithm)aMax : (Algorithm)(selectedAlgorithm - 1); TempText.setTempText($"Selected algorithm: {selectedAlgorithm.ToString()}", 3); } if (Input.GetKeyDown(KeyCode.RightBracket)) { selectedAlgorithm = ((int)selectedAlgorithm) == aMax ? (Algorithm)aMin : (Algorithm)(selectedAlgorithm + 1); TempText.setTempText($"Selected algorithm: {selectedAlgorithm.ToString()}", 3); } if (Input.GetKeyDown(KeyCode.Semicolon)) { iterationMode = ((int)iterationMode) == iMin ? (IterationMode)iMax : (IterationMode)(iterationMode - 1); TempText.setTempText($"Selected iteration mode: {iterationMode.ToString()}", 3); } if (Input.GetKeyDown(KeyCode.Quote)) { iterationMode = ((int)iterationMode) == iMax ? (IterationMode)iMin : (IterationMode)(iterationMode + 1); TempText.setTempText($"Selected iteration mode: {iterationMode.ToString()}", 3); } }
private List <Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { var measurements = new List <Measurement>(); int iterationCounter = 0; bool isIdle = iterationMode.IsIdle(); double maxErrorRelative = isIdle ? MaxIdleStdErrRelative : Resolver.Resolve(TargetAccuracy.MaxStdErrRelative); while (true) { iterationCounter++; var measurement = RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor); measurements.Add(measurement); var statistics = new Statistics(measurements.Select(m => m.Nanoseconds)); if (Resolver.Resolve(TargetAccuracy.RemoveOutliers)) { statistics = new Statistics(statistics.WithoutOutliers()); } double actualError = statistics.StandardError; double maxError = maxErrorRelative * statistics.Mean; if (iterationCounter >= MinIterationCount && actualError < maxError) { break; } if (iterationCounter >= MaxIterationCount || (isIdle && iterationCounter >= MaxIdleIterationCount)) { break; } } WriteLine(); return(measurements); }
public override string ToString() { var builder = new StringBuilder(); builder.Append((IterationMode.ToString() + IterationStage).PadRight(IterationInfoNameMaxWidth, ' ')); builder.Append(' '); // Usually, a benchmarks takes more than 10 iterations (rarely more than 99) // PadLeft(2, ' ') looks like a good trade-off between alignment and amount of characters builder.Append(IterationIndex.ToString(MainCultureInfo).PadLeft(2, ' ')); builder.Append(": "); builder.Append(Operations.ToString(MainCultureInfo)); builder.Append(' '); builder.Append(OpSymbol); builder.Append(", "); builder.Append(Nanoseconds.ToString("0.00", MainCultureInfo)); builder.Append(' '); builder.Append(NsSymbol); builder.Append(", "); builder.Append(GetAverageTime().ToString(MainCultureInfo).ToAscii()); builder.Append("/op"); return(builder.ToString()); }
private bool IsWarmupFinished(List <Measurement> measurements, IterationMode iterationMode) { int n = measurements.Count; if (n >= maxIterationCount || iterationMode == IterationMode.Overhead && n >= MaxOverheadIterationCount) { return(true); } if (n < minIterationCount) { return(false); } int dir = -1, changeCount = 0; for (int i = 1; i < n; i++) { int nextDir = Math.Sign(measurements[i].Nanoseconds - measurements[i - 1].Nanoseconds); if (nextDir != dir || nextDir == 0) { dir = nextDir; changeCount++; } } return(changeCount >= 4); }
public IterationData(IterationMode iterationMode, int index, long invokeCount, int unrollFactor) { IterationMode = iterationMode; Index = index; InvokeCount = invokeCount; UnrollFactor = unrollFactor; }
private Measurement MultiInvoke( IterationMode mode, int index, Action setupAction, Action targetAction, long invocationCount, long operationsPerInvoke) { var totalOperations = invocationCount * operationsPerInvoke; setupAction(); ClockSpan clockSpan; GcCollect(); if (invocationCount == 1) { var chronometer = Chronometer.Start(); targetAction(); clockSpan = chronometer.Stop(); } else if (invocationCount < int.MaxValue) { int intInvocationCount = (int)invocationCount; var chronometer = Chronometer.Start(); RunAction(targetAction, intInvocationCount); clockSpan = chronometer.Stop(); } else { var chronometer = Chronometer.Start(); RunAction(targetAction, invocationCount); clockSpan = chronometer.Stop(); } var measurement = new Measurement(0, mode, index, totalOperations, clockSpan.GetNanoseconds()); Console.WriteLine(measurement.ToOutputLine()); GcCollect(); return(measurement); }
public IEnumerable <T> GetItemEnumerable(IterationMode mode = IterationMode.Linear, IterationDirection direction = IterationDirection.Forward) { switch (mode) { case IterationMode.Linear: foreach (var node in LinearEnumerable(direction)) { yield return(node.Value); } yield break; case IterationMode.Circular: foreach (var node in CircularEnumerable(direction)) { yield return(node.Value); } yield break; case IterationMode.Harmonic: foreach (var node in HarmonicEnumerable(direction)) { yield return(node.Value); } yield break; default: yield break; } }
private static bool IsWarmupFinished(List <Measurement> measurements, IterationMode iterationMode) { int n = measurements.Count; if (n >= MaxIterationCount || (iterationMode.IsIdle() && n >= MaxIdleItertaionCount)) { return(true); } if (n < MinIterationCount) { return(false); } int dir = -1, changeCount = 0; for (int i = 1; i < n; i++) { int nextDir = Math.Sign(measurements[i].Nanoseconds - measurements[i - 1].Nanoseconds); if (nextDir != dir || nextDir == 0) { dir = nextDir; changeCount++; } } return(changeCount >= 4); }
private List<Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { var measurements = new List<Measurement>(MaxIterationCount); var measurementsForStatistics = new List<Measurement>(MaxIterationCount); int iterationCounter = 0; bool isIdle = iterationMode.IsIdle(); double maxErrorRelative = isIdle ? MaxIdleStdErrRelative : maxStdErrRelative; while (true) { iterationCounter++; var measurement = RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor); measurements.Add(measurement); measurementsForStatistics.Add(measurement); var statistics = MeasurementsStatistics.Calculate(measurementsForStatistics, removeOutliers); double actualError = statistics.StandardError; double maxError = maxErrorRelative * statistics.Mean; if (iterationCounter >= MinIterationCount && actualError < maxError) break; if (iterationCounter >= MaxIterationCount || (isIdle && iterationCounter >= MaxIdleIterationCount)) break; } if (!IsDiagnoserAttached) WriteLine(); return measurements; }
private List <Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { int iterationCounter = 0; bool isIdle = iterationMode.IsIdle(); double maxErrorRelative = isIdle ? MaxIdleStdErrRelative : maxStdErrRelative; while (true) { iterationCounter++; var measurement = RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor); measurements.Add(measurement); var statistics = MeasurementsStatistics.Calculate(measurements, removeOutliers); double actualError = statistics.StandardError; double maxError = maxErrorRelative * statistics.Mean; if (iterationCounter >= MinIterationCount && actualError < maxError) { break; } if (iterationCounter >= MaxIterationCount || (isIdle && iterationCounter >= MaxIdleIterationCount)) { break; } } if (!IsDiagnoserAttached) { WriteLine(); } return(measurements); }
protected Measurement RunIteration(IterationMode mode, int index, long invokeCount, int unrollFactor) { if (invokeCount % unrollFactor != 0) { throw new ArgumentOutOfRangeException($"InvokeCount({invokeCount}) should be a multiple of UnrollFactor({unrollFactor})."); } return(engine.RunIteration(new IterationData(mode, index, invokeCount, unrollFactor))); }
/// <summary> /// Creates an instance of <see cref="Measurement"/> class. /// </summary> /// <param name="launchIndex"></param> /// <param name="iterationMode"></param> /// <param name="iterationIndex"></param> /// <param name="operations">The number of operations performed.</param> /// <param name="nanoseconds">The total number of nanoseconds it took to perform all operations.</param> public Measurement(int launchIndex, IterationMode iterationMode, int iterationIndex, long operations, double nanoseconds) { IterationMode = iterationMode; IterationIndex = iterationIndex; Operations = operations; Nanoseconds = nanoseconds; LaunchIndex = launchIndex; }
/// <summary> /// Creates an instance of <see cref="Measurement"/> struct. /// </summary> /// <param name="launchIndex"></param> /// <param name="iterationMode"></param> /// <param name="iterationIndex"></param> /// <param name="operations">The number of operations performed.</param> /// <param name="nanoseconds">The total number of nanoseconds it took to perform all operations.</param> /// <param name="encoding">encoding to display value.</param> public Measurement(int launchIndex, IterationMode iterationMode, int iterationIndex, long operations, double nanoseconds, Encoding encoding = null) { Encoding = encoding; Operations = operations; Nanoseconds = nanoseconds; LaunchIndex = launchIndex; IterationMode = iterationMode; IterationIndex = iterationIndex; }
public string ToOutputLine() { string alignedIterationMode = IterationMode.ToString().PadRight(IterationModeNameMaxWidth, ' '); // Usually, a benchmarks takes more than 10 iterations (rarely more than 99) // PadLeft(2, ' ') looks like a good trade-off between alignment and amount of characters string alignedIterationIndex = IterationIndex.ToString().PadLeft(2, ' '); return($"{alignedIterationMode} {alignedIterationIndex}: {GetDisplayValue()}"); }
private void HandleIterationEvent(int processId, double timeStampRelative, IterationMode iterationMode, long totalOperations) { // if given process emits Benchmarking events it's the process that we care about if (!processIdToData.ContainsKey(processId)) { processIdToData.Add(processId, new ProcessMetrics()); } processIdToData[processId].HandleIterationEvent(timeStampRelative, iterationMode, totalOperations); }
private void AutoTest(Func<IterationData, TimeInterval> measure, int min, int max = -1, IterationMode mode = IterationMode.MainWarmup) { if (max == -1) max = min; var job = Job.Default; var stage = CreateStage(job, measure); var measurements = stage.Run(1, mode, true, 1); int count = measurements.Count; output.WriteLine($"MeasurementCount = {count} (Min= {min}, Max = {max})"); Assert.InRange(count, min, max); }
private List<Measurement> RunSpecific(long invokeCount, IterationMode iterationMode, int iterationCount, int unrollFactor) { var measurements = new List<Measurement>(MaxIterationCount); for (int i = 0; i < iterationCount; i++) measurements.Add(RunIteration(iterationMode, i + 1, invokeCount, unrollFactor)); if (!IsDiagnoserAttached) WriteLine(); return measurements; }
private List <Measurement> RunSpecific(long invokeCount, IterationMode iterationMode, int iterationCount) { var measurements = new List <Measurement>(iterationCount); for (int i = 0; i < iterationCount; i++) { measurements.Add(RunIteration(iterationMode, i + 1, invokeCount)); } WriteLine(); return(measurements); }
private List <Measurement> RunSpecific(long invokeCount, IterationMode iterationMode, int iterationCount, int unrollFactor) { var measurements = new List <Measurement>(MaxIterationCount); for (int i = 0; i < iterationCount; i++) { measurements.Add(RunIteration(iterationMode, IterationStage.Warmup, i + 1, invokeCount, unrollFactor)); } WriteLine(); return(measurements); }
public void UpdateLineRenderer(IterationMode mode, int resolution) { if (lineRenderer == null) { return; } List <Vector3> tempPoints = new List <Vector3>(); switch (mode) { case IterationMode.Linear: { for (int i = 0; i < curve.CountSegments; i++) { for (float p = 0f; p < 1f; p += 1.0f / resolution) { tempPoints.Add(curve.Evaluate(i, p)); } // Manually adding last position due to floating point inaccuracies if (i >= curve.CountSegments - 1) { tempPoints.Add(curve.Evaluate(i, 1.0f)); } } break; } case IterationMode.Curvature: { break; } default: { break; } } lineRenderer.positionCount = tempPoints.Count; lineRenderer.SetPositions(tempPoints.ToArray()); lineRenderer.startWidth = curve.s_displayWidthCurve; lineRenderer.endWidth = curve.s_displayWidthCurve; if (lineRenderer.sharedMaterial == null) { var tempMat = Resources.Load("Materials/XplinesLineRenderer", typeof(Material)) as Material; lineRenderer.sharedMaterial = tempMat; } }
private List <Measurement> RunSpecific(long invokeCount, IterationMode iterationMode, int iterationCount, int unrollFactor) { for (int i = 0; i < iterationCount; i++) { measurements.Add(RunIteration(iterationMode, i + 1, invokeCount, unrollFactor)); } if (!IsDiagnoserAttached) { WriteLine(); } return(measurements); }
public virtual IStoppingCriteria CreateWarmup(Job job, IResolver resolver, IterationMode mode, RunStrategy runStrategy) { switch (mode) { case IterationMode.Overhead: return(CreateWarmupOverhead()); case IterationMode.Workload: return(CreateWarmupWorkload(job, resolver, runStrategy)); default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } }
private void RunCore( IterationMode iterationMode, int repeatCount, List <Measurement> measurements) { DebugCode.BugIf(measurements.Count > 0, "measurements not empty."); DebugCode.BugIf(measurements.Capacity < repeatCount, "measurements capacity not set."); var action = iterationMode.IsIdle() ? IdleAction : MainAction; var resultIterationsCount = ResultIterationsCount; // TODO: reenable after https://github.com/dotnet/BenchmarkDotNet/issues/302#issuecomment-262057686 //if (!iterationMode.IsIdle()) // SetupAction?.Invoke(); ForceGcCollect(); if (ForceAllocations) // DONTTOUCH: DO NOT merge loops as it will produce inaccurate results for microbenchmarks. { for (var i = 0; i < repeatCount; i++) { ForceGcCollect(); var clock = Clock.Start(); action(resultIterationsCount); var clockSpan = clock.Stop(); measurements.Add( new Measurement(0, iterationMode, i + 1, 1, clockSpan.GetNanoseconds())); } } else { for (var i = 0; i < repeatCount; i++) { var clock = Clock.Start(); action(resultIterationsCount); var clockSpan = clock.Stop(); measurements.Add( new Measurement(0, iterationMode, i + 1, 1, clockSpan.GetNanoseconds())); } } ForceGcCollect(); // TODO: reenable after https://github.com/dotnet/BenchmarkDotNet/issues/302#issuecomment-262057686 //if (!iterationMode.IsIdle()) // CleanupAction?.Invoke(); }
private List<Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { var measurements = new List<Measurement>(MaxIterationCount); int iterationCounter = 0; while (true) { iterationCounter++; measurements.Add(RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor)); if (IsWarmupFinished(measurements, iterationMode)) break; } if (!IsDiagnoserAttached) WriteLine(); return measurements; }
private static IList <Measurement> RunTarget( Func <MultiInvokeInput, Measurement> multiInvoke, long invokeCount, IterationMode iterationMode, Count iterationCount) { var measurements = new List <Measurement>(); if (iterationCount.IsAuto) { int iterationCounter = 0; bool isIdle = ShouldCallIdle(iterationMode); var maxAcceptableError = isIdle ? TargetIdleAutoMaxAcceptableError : TargetMainAutoMaxAcceptableError; ForceGcCollect(); while (true) { iterationCounter++; var measurement = multiInvoke(new MultiInvokeInput(iterationMode, iterationCounter, invokeCount)); measurements.Add(measurement); var statistics = new Statistics(measurements.Select(m => m.Nanoseconds)); var statisticsWithoutOutliers = new Statistics(statistics.WithoutOutliers()); if (iterationCounter >= TargetAutoMinIterationCount && statisticsWithoutOutliers.StandardError < maxAcceptableError * statisticsWithoutOutliers.Mean) { break; } if (isIdle && iterationCounter >= TargetIdleAutoMaxIterationCount) { break; } } ForceGcCollect(); } else { ForceGcCollect(); for (int i = 0; i < iterationCount; i++) { measurements.Add(multiInvoke(new MultiInvokeInput(IterationMode.MainTarget, i + 1, invokeCount))); } ForceGcCollect(); } Console.WriteLine(); return(measurements); }
private void RunCore <T>( Action setupAction, Func <T> targetAction, IterationMode iterationMode, Count iterationCount) { ForceGcCollect(); setupAction(); for (int i = 0; i < iterationCount; i++) { var chronometer = Chronometer.Start(); targetAction(); var clockSpan = chronometer.Stop(); var measurement = new Measurement(0, iterationMode, i + 1, 1, clockSpan.GetNanoseconds()); _allMeasurements.Add(measurement); } ForceGcCollect(); }
private List <Measurement> RunAuto(long invokeCount, IterationMode iterationMode) { int iterationCounter = 0; var measurements = new List <Measurement>(MaxIterationCount); while (true) { iterationCounter++; measurements.Add(RunIteration(iterationMode, iterationCounter, invokeCount)); if (IsWarmupFinished(measurements, iterationMode)) { break; } } WriteLine(); return(measurements); }
private Measurement MultiInvoke <T>(IterationMode mode, int index, Action setupAction, Func <T> targetAction, long invocationCount, long operationsPerInvoke, T returnHolder = default(T)) { State.Instance.IterationMode = mode; State.Instance.Iteration = index; var totalOperations = invocationCount * operationsPerInvoke; setupAction(); ClockSpan clockSpan; GcCollect(); if (invocationCount == 1) { var chronometer = Chronometer.Start(); returnHolder = targetAction(); clockSpan = chronometer.Stop(); } else if (invocationCount < int.MaxValue) { int intInvocationCount = (int)invocationCount; var chronometer = Chronometer.Start(); for (int i = 0; i < intInvocationCount; i++) { State.Instance.Operation = i; returnHolder = targetAction(); } clockSpan = chronometer.Stop(); } else { var chronometer = Chronometer.Start(); for (long i = 0; i < invocationCount; i++) { State.Instance.Operation = i; returnHolder = targetAction(); } clockSpan = chronometer.Stop(); } multiInvokeReturnHolder = returnHolder; var measurement = new Measurement(0, mode, index, totalOperations, clockSpan.GetNanoseconds()); Console.WriteLine(measurement.ToOutputLine()); GcCollect(); return(measurement); }
public IEnumerable <LinkedListNode <T> > GetNodeEnumerable(IterationMode mode = IterationMode.Linear, IterationDirection direction = IterationDirection.Forward) { switch (mode) { case IterationMode.Linear: return(LinearEnumerable(direction)); case IterationMode.Circular: return(CircularEnumerable(direction)); case IterationMode.Harmonic: return(HarmonicEnumerable(direction)); default: return(null); } }
public void Start() { //initialze object references selectionRef = Resources.Load("Selection") as GameObject; outputRef = Resources.Load("Output") as GameObject; //switching algorithms aMax = (int)Enum.GetValues(typeof(Algorithm)).Cast <Algorithm>().Max(); aMin = (int)Enum.GetValues(typeof(Algorithm)).Cast <Algorithm>().Min(); //switching iteration modes iMax = (int)Enum.GetValues(typeof(IterationMode)).Cast <IterationMode>().Max(); iMin = (int)Enum.GetValues(typeof(IterationMode)).Cast <IterationMode>().Min(); player = GetComponent <Player>(); //defaults selectedAlgorithm = 0; iterationMode = 0; }
private List <Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { int iterationCounter = 0; while (true) { iterationCounter++; measurements.Add(RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor)); if (IsWarmupFinished(measurements, iterationMode)) { break; } } if (!IsDiagnoserAttached) { WriteLine(); } return(measurements); }
private static bool IsWarmupFinished(List<Measurement> measurements, IterationMode iterationMode) { int n = measurements.Count; if (n >= MaxIterationCount || (iterationMode.IsIdle() && n >= MaxIdleItertaionCount)) return true; if (n < MinIterationCount) return false; int dir = -1, changeCount = 0; for (int i = 1; i < n; i++) { int nextDir = Math.Sign(measurements[i].Nanoseconds - measurements[i - 1].Nanoseconds); if (nextDir != dir || nextDir == 0) { dir = nextDir; changeCount++; } } return changeCount >= 4; }
private static void RunWarmup( Func <MultiInvokeInput, Measurement> multiInvoke, long invokeCount, IterationMode iterationMode, Count iterationCount) { if (iterationCount.IsAuto) { ForceGcCollect(); int iterationCounter = 0; Measurement previousMeasurement = null; int upCount = 0; while (true) { iterationCounter++; var measurement = multiInvoke(new MultiInvokeInput(iterationMode, iterationCounter, invokeCount)); if (previousMeasurement != null && measurement.Nanoseconds > previousMeasurement.Nanoseconds - 0.1) { upCount++; } if (iterationCounter >= WarmupAutoMinIterationCount && upCount >= 3) { break; } previousMeasurement = measurement; } ForceGcCollect(); } else { ForceGcCollect(); for (int i = 0; i < iterationCount; i++) { multiInvoke(new MultiInvokeInput(IterationMode.MainWarmup, i + 1, invokeCount)); } ForceGcCollect(); } Console.WriteLine(); }
private List <Measurement> RunAuto(long invokeCount, IterationMode iterationMode, int unrollFactor) { var measurements = measurementsPool.Next(); var measurementsForStatistics = measurementsPool.Next(); int iterationCounter = 0; bool isIdle = iterationMode.IsIdle(); double effectiveMaxRelativeError = isIdle ? MaxIdleRelativeError : maxRelativeError; while (true) { iterationCounter++; var measurement = RunIteration(iterationMode, iterationCounter, invokeCount, unrollFactor); measurements.Add(measurement); measurementsForStatistics.Add(measurement); var statistics = MeasurementsStatistics.Calculate(measurementsForStatistics, removeOutliers); double actualError = statistics.ConfidenceInterval.Margin; double maxError1 = effectiveMaxRelativeError * statistics.Mean; double maxError2 = maxAbsoluteError?.Nanoseconds ?? double.MaxValue; double maxError = Math.Min(maxError1, maxError2); if (iterationCounter >= MinIterationCount && actualError < maxError) { break; } if (iterationCounter >= MaxIterationCount || (isIdle && iterationCounter >= MaxIdleIterationCount)) { break; } } if (!IsDiagnoserAttached) { WriteLine(); } return(measurements); }
internal List<Measurement> Run(long invokeCount, IterationMode iterationMode, bool runAuto, int unrollFactor) => runAuto || warmupCount == null ? RunAuto(invokeCount, iterationMode, unrollFactor) : RunSpecific(invokeCount, iterationMode, warmupCount.Value, unrollFactor);
protected Measurement RunIteration(IterationMode mode, int index, long invokeCount, int unrollFactor) { if (invokeCount % unrollFactor != 0) throw new ArgumentOutOfRangeException($"InvokeCount({invokeCount}) should be a multiple of UnrollFactor({unrollFactor})."); return engine.RunIteration(new IterationData(mode, index, invokeCount, unrollFactor)); }
internal IReadOnlyList<Measurement> Run(long invokeCount, IterationMode iterationMode, bool runAuto, int unrollFactor) => runAuto || targetCount == null ? RunAuto(invokeCount, iterationMode, unrollFactor) : RunSpecific(invokeCount, iterationMode, targetCount.Value, unrollFactor);