/// <summary>Creates the <see cref="BurstModeEngine"/>.</summary> /// <param name="engineParameters">The engine parameters.</param> /// <returns>Instance of <see cref="BurstModeEngine"/>.</returns> public IEngine Create(EngineParameters engineParameters) { if (engineParameters.MainAction == null) { throw new ArgumentNullException(nameof(engineParameters.MainAction)); } if (engineParameters.IdleAction == null) { throw new ArgumentNullException(nameof(engineParameters.IdleAction)); } if (engineParameters.TargetJob == null) { throw new ArgumentNullException(nameof(engineParameters.TargetJob)); } var targetJob = engineParameters.TargetJob; if (!targetJob.HasValue(RunMode.InvocationCountCharacteristic) || !targetJob.HasValue(RunMode.WarmupCountCharacteristic) || !targetJob.HasValue(RunMode.TargetCountCharacteristic)) { throw new ArgumentException( $"Please set the {RunMode.InvocationCountCharacteristic.FullId}," + $"{RunMode.WarmupCountCharacteristic.FullId} and " + $"{RunMode.TargetCountCharacteristic.FullId} values .", nameof(engineParameters)); } return(new BurstModeEngine(engineParameters)); }
private static Engine CreateSingleActionEngine(EngineParameters engineParameters) => CreateEngine(engineParameters, engineParameters.TargetJob .WithInvocationCount(1).WithUnrollFactor(1) // run the benchmark exactly once per iteration .WithEvaluateOverhead(false), // it's something very time consuming, it overhead is too small compared to total time // todo: consider if we should set the warmup count to 2 engineParameters.OverheadActionNoUnroll, engineParameters.WorkloadActionNoUnroll);
private static Engine CreateEngine(EngineParameters engineParameters, Job job, Action <long> idle, Action <long> main) => new Engine( engineParameters.Host, EngineParameters.DefaultResolver, engineParameters.Dummy1Action, engineParameters.Dummy2Action, engineParameters.Dummy3Action, idle, main, job, engineParameters.GlobalSetupAction, engineParameters.GlobalCleanupAction, engineParameters.IterationSetupAction, engineParameters.IterationCleanupAction, engineParameters.OperationsPerInvoke, engineParameters.MeasureGcStats);
public IEngine Create(EngineParameters engineParameters) { if (engineParameters.MainAction == null) throw new ArgumentNullException(nameof(engineParameters.MainAction)); if (engineParameters.IdleAction == null) throw new ArgumentNullException(nameof(engineParameters.IdleAction)); if(engineParameters.TargetJob == null) throw new ArgumentNullException(nameof(engineParameters.TargetJob)); return new Engine( engineParameters.IdleAction, engineParameters.MainAction, engineParameters.TargetJob, engineParameters.SetupAction, engineParameters.CleanupAction, engineParameters.OperationsPerInvoke, engineParameters.IsDiagnoserAttached); }
public IEngine Create(EngineParameters engineParameters) { if (engineParameters.MainAction == null) { throw new ArgumentNullException(nameof(engineParameters.MainAction)); } if (engineParameters.Dummy1Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy1Action)); } if (engineParameters.Dummy2Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy2Action)); } if (engineParameters.Dummy3Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy3Action)); } if (engineParameters.IdleAction == null) { throw new ArgumentNullException(nameof(engineParameters.IdleAction)); } if (engineParameters.TargetJob == null) { throw new ArgumentNullException(nameof(engineParameters.TargetJob)); } return(new Engine( engineParameters.Host, engineParameters.Dummy1Action, engineParameters.Dummy2Action, engineParameters.Dummy3Action, engineParameters.IdleAction, engineParameters.MainAction, engineParameters.TargetJob, engineParameters.GlobalSetupAction, engineParameters.GlobalCleanupAction, engineParameters.IterationSetupAction, engineParameters.IterationCleanupAction, engineParameters.OperationsPerInvoke, engineParameters.MeasureGcStats)); }
public IEngine Create(EngineParameters engineParameters) { if (engineParameters.MainAction == null) { throw new ArgumentNullException(nameof(engineParameters.MainAction)); } if (engineParameters.Dummy1Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy1Action)); } if (engineParameters.Dummy2Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy2Action)); } if (engineParameters.Dummy3Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy3Action)); } if (engineParameters.IdleAction == null) { throw new ArgumentNullException(nameof(engineParameters.IdleAction)); } if (engineParameters.TargetJob == null) { throw new ArgumentNullException(nameof(engineParameters.TargetJob)); } return(new Engine( engineParameters.Dummy1Action, engineParameters.Dummy2Action, engineParameters.Dummy3Action, engineParameters.IdleAction, engineParameters.MainAction, engineParameters.TargetJob, engineParameters.SetupAction, engineParameters.CleanupAction, engineParameters.OperationsPerInvoke, engineParameters.IsDiagnoserAttached)); }
/// <summary>Initializes a new instance of the <see cref="BurstModeEngine"/> class.</summary> /// <param name="engineParameters">The engine parameters.</param> public BurstModeEngine(EngineParameters engineParameters) { _engineParameters = engineParameters; Resolver = new CompositeResolver( EnvResolver.Instance, InfrastructureResolver.Instance, EngineResolver.Instance); var targetJob = engineParameters.TargetJob; Clock = targetJob.ResolveValue(InfrastructureMode.ClockCharacteristic, Resolver); ForceAllocations = targetJob.ResolveValue(GcMode.ForceCharacteristic, Resolver); UnrollFactor = targetJob.ResolveValue(RunMode.UnrollFactorCharacteristic, Resolver); Strategy = targetJob.ResolveValue(RunMode.RunStrategyCharacteristic, Resolver); EvaluateOverhead = targetJob.ResolveValue(AccuracyMode.EvaluateOverheadCharacteristic, Resolver); RemoveOutliers = targetJob.ResolveValue(AccuracyMode.RemoveOutliersCharacteristic, Resolver); InvocationCount = targetJob.ResolveValue(RunMode.InvocationCountCharacteristic, Resolver); WarmupCount = targetJob.ResolveValueAsNullable(RunMode.WarmupCountCharacteristic) ?? 1; TargetCount = targetJob.ResolveValueAsNullable(RunMode.TargetCountCharacteristic) ?? 1; IdleWarmupList = new List <Measurement>(WarmupCount); WarmupList = new List <Measurement>(WarmupCount); IdleTargetList = new List <Measurement>(TargetCount); TargetList = new List <Measurement>(TargetCount); var resultCount = OperationsPerInvoke * InvocationCount; if (resultCount % UnrollFactor != 0) { throw new ArgumentOutOfRangeException( $"InvokeCount({resultCount}) should be a multiple of UnrollFactor({UnrollFactor})."); } ResultIterationsCount = resultCount / UnrollFactor; }
public IEngine CreateReadyToRun(EngineParameters engineParameters) { if (engineParameters.WorkloadActionNoUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.WorkloadActionNoUnroll)); } if (engineParameters.WorkloadActionUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.WorkloadActionUnroll)); } if (engineParameters.Dummy1Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy1Action)); } if (engineParameters.Dummy2Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy2Action)); } if (engineParameters.Dummy3Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy3Action)); } if (engineParameters.OverheadActionNoUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.OverheadActionNoUnroll)); } if (engineParameters.OverheadActionUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.OverheadActionUnroll)); } if (engineParameters.TargetJob == null) { throw new ArgumentNullException(nameof(engineParameters.TargetJob)); } engineParameters.GlobalSetupAction?.Invoke(); // whatever the settings are, we MUST call global setup here, the global cleanup is part of Engine's Dispose if (!engineParameters.NeedsJitting) // just create the engine, do NOT jit { return(CreateMultiActionEngine(engineParameters)); } int jitIndex = 0; if (engineParameters.HasInvocationCount || engineParameters.HasUnrollFactor) // it's a job with explicit configuration, just create the engine and jit it { var warmedUpMultiActionEngine = CreateMultiActionEngine(engineParameters); DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(warmedUpMultiActionEngine, ++jitIndex, invokeCount: engineParameters.UnrollFactor, unrollFactor: engineParameters.UnrollFactor)); return(warmedUpMultiActionEngine); } var singleActionEngine = CreateSingleActionEngine(engineParameters); var singleInvocationTime = Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1); if (singleInvocationTime > engineParameters.IterationTime) { return(singleActionEngine); // executing once takes longer than iteration time => long running benchmark, needs no pilot and no overhead } int defaultUnrollFactor = Job.Default.ResolveValue(RunMode.UnrollFactorCharacteristic, EngineParameters.DefaultResolver); double timesPerIteration = engineParameters.IterationTime / singleInvocationTime; // how many times can we run given benchmark per iteration if (timesPerIteration < 1.5) // example: IterationTime is 0.5s, but single invocation takes 0.4s => we don't want to run it twice per iteration { return(singleActionEngine); } int roundedUpTimesPerIteration = (int)Math.Ceiling(timesPerIteration); if (roundedUpTimesPerIteration < defaultUnrollFactor) // if we run it defaultUnrollFactor times per iteration, it's going to take longer than IterationTime { var needsPilot = engineParameters.TargetJob .WithUnrollFactor(1) // we don't want to use unroll factor! .WithMinInvokeCount(2) // the minimum is 2 (not the default 4 which can be too much and not 1 which we already know is not enough) .WithEvaluateOverhead(false); // it's something very time consuming, it overhead is too small compared to total time return(CreateEngine(engineParameters, needsPilot, engineParameters.OverheadActionNoUnroll, engineParameters.WorkloadActionNoUnroll)); } var multiActionEngine = CreateMultiActionEngine(engineParameters); DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine, ++jitIndex, invokeCount: defaultUnrollFactor, unrollFactor: defaultUnrollFactor)); return(multiActionEngine); }
private static Engine CreateMultiActionEngine(EngineParameters engineParameters) => CreateEngine(engineParameters, engineParameters.TargetJob, engineParameters.OverheadActionUnroll, engineParameters.WorkloadActionUnroll);
public IEngine Create(EngineParameters engineParameters) => new CustomEngine { CleanupAction = engineParameters.CleanupAction, SetupAction = engineParameters.SetupAction };
private static Engine CreateMultiActionEngine(EngineParameters engineParameters) => CreateEngine(engineParameters, engineParameters.TargetJob, engineParameters.IdleActionUnroll, engineParameters.MainActionUnroll);
public IEngine CreateReadyToRun(EngineParameters engineParameters) { if (engineParameters.WorkloadActionNoUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.WorkloadActionNoUnroll)); } if (engineParameters.WorkloadActionUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.WorkloadActionUnroll)); } if (engineParameters.Dummy1Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy1Action)); } if (engineParameters.Dummy2Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy2Action)); } if (engineParameters.Dummy3Action == null) { throw new ArgumentNullException(nameof(engineParameters.Dummy3Action)); } if (engineParameters.OverheadActionNoUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.OverheadActionNoUnroll)); } if (engineParameters.OverheadActionUnroll == null) { throw new ArgumentNullException(nameof(engineParameters.OverheadActionUnroll)); } if (engineParameters.TargetJob == null) { throw new ArgumentNullException(nameof(engineParameters.TargetJob)); } engineParameters.GlobalSetupAction?.Invoke(); // whatever the settings are, we MUST call global setup here, the global cleanup is part of Engine's Dispose if (!engineParameters.NeedsJitting) // just create the engine, do NOT jit { return(CreateMultiActionEngine(engineParameters)); } int jitIndex = 0; if (engineParameters.HasInvocationCount || engineParameters.HasUnrollFactor) // it's a job with explicit configuration, just create the engine and jit it { var warmedUpMultiActionEngine = CreateMultiActionEngine(engineParameters); DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(warmedUpMultiActionEngine, ++jitIndex, invokeCount: engineParameters.UnrollFactor, unrollFactor: engineParameters.UnrollFactor)); return(warmedUpMultiActionEngine); } var singleActionEngine = CreateSingleActionEngine(engineParameters); var singleInvocationTime = Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1); double timesPerIteration = engineParameters.IterationTime / singleInvocationTime; // how many times can we run given benchmark per iteration if ((timesPerIteration < 1.5) && (singleInvocationTime < TimeInterval.FromSeconds(10.0))) { // if the Jitting took more than IterationTime/1.5 but still less than 10s (a magic number based on observations of reported bugs) // we call it one more time to see if Jitting itself has not dominated the first invocation // if it did, it should NOT be a single invocation engine (see #837, #1337, #1338, and #1780) singleInvocationTime = Jit(singleActionEngine, ++jitIndex, invokeCount: 1, unrollFactor: 1); timesPerIteration = engineParameters.IterationTime / singleInvocationTime; } // executing once takes longer than iteration time => long running benchmark, needs no pilot and no overhead // Or executing twice would put us well past the iteration time ==> needs no pilot and no overhead if (timesPerIteration < 1.5) { return(singleActionEngine); } int defaultUnrollFactor = Job.Default.ResolveValue(RunMode.UnrollFactorCharacteristic, EngineParameters.DefaultResolver); int roundedUpTimesPerIteration = (int)Math.Ceiling(timesPerIteration); if (roundedUpTimesPerIteration < defaultUnrollFactor) // if we run it defaultUnrollFactor times per iteration, it's going to take longer than IterationTime { var needsPilot = engineParameters.TargetJob .WithUnrollFactor(1) // we don't want to use unroll factor! .WithMinInvokeCount(2) // the minimum is 2 (not the default 4 which can be too much and not 1 which we already know is not enough) .WithEvaluateOverhead(false); // it's something very time consuming, it overhead is too small compared to total time return(CreateEngine(engineParameters, needsPilot, engineParameters.OverheadActionNoUnroll, engineParameters.WorkloadActionNoUnroll)); } var multiActionEngine = CreateMultiActionEngine(engineParameters); DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine, ++jitIndex, invokeCount: defaultUnrollFactor, unrollFactor: defaultUnrollFactor)); return(multiActionEngine); }