Skip to content

Commit

Permalink
do the math right for unroll factor for JIT, #736
Browse files Browse the repository at this point in the history
  • Loading branch information
adamsitnik committed May 22, 2018
1 parent 343a603 commit c1d8ac6
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 9 deletions.
11 changes: 6 additions & 5 deletions src/BenchmarkDotNet/Engines/EngineFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
throw new ArgumentNullException(nameof(engineParameters.TargetJob));

var resolver = new CompositeResolver(BenchmarkRunner.DefaultResolver, EngineResolver.Instance);
var unrollFactor = engineParameters.TargetJob.ResolveValue(RunMode.UnrollFactorCharacteristic, resolver);

engineParameters.GlobalSetupAction?.Invoke();

Expand All @@ -45,7 +46,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
var singleActionEngine = CreateEngine(engineParameters, resolver, engineParameters.TargetJob, engineParameters.IdleSingleAction, engineParameters.MainSingleAction);

var iterationTime = resolver.Resolve(engineParameters.TargetJob, RunMode.IterationTimeCharacteristic);
if (ShouldExecuteOncePerIteration(Jit(singleActionEngine), iterationTime))
if (ShouldExecuteOncePerIteration(Jit(singleActionEngine, unrollFactor: 1), iterationTime))
{
var reconfiguredJob = engineParameters.TargetJob.WithInvocationCount(1).WithUnrollFactor(1); // todo: consider if we should set the warmup count to 1!

Expand All @@ -56,7 +57,7 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
// it's either a job with explicit configuration or not-very time consuming benchmark, just create the engine, Jit and return
var multiActionEngine = CreateEngine(engineParameters, resolver, engineParameters.TargetJob, engineParameters.IdleMultiAction, engineParameters.MainMultiAction);

DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine));
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(Jit(multiActionEngine, unrollFactor));

return multiActionEngine;
}
Expand All @@ -67,11 +68,11 @@ public IEngine CreateReadyToRun(EngineParameters engineParameters)
private static bool ShouldExecuteOncePerIteration(Measurement jit, TimeInterval iterationTime)
=> TimeInterval.FromNanoseconds(jit.GetAverageNanoseconds()) > iterationTime;

private static Measurement Jit(Engine engine)
private static Measurement Jit(Engine engine, int unrollFactor)
{
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.IdleJit, index: -1, invokeCount: 1, unrollFactor: 1))); // don't forget to JIT idle
DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.IdleJit, index: -1, invokeCount: unrollFactor, unrollFactor: unrollFactor))); // don't forget to JIT idle

return engine.RunIteration(new IterationData(IterationMode.Jit, index: -1, invokeCount: 1, unrollFactor: 1));
return engine.RunIteration(new IterationData(IterationMode.Jit, index: -1, invokeCount: unrollFactor, unrollFactor: unrollFactor));
}

private static Engine CreateEngine(EngineParameters engineParameters, IResolver resolver, Job job, Action<long> idle, Action<long> main)
Expand Down
8 changes: 4 additions & 4 deletions tests/BenchmarkDotNet.Tests/Engine/EngineFactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ public void VeryTimeConsumingBenchmarksAreExecutedOncePerIterationForDefaultSett
var engine = new EngineFactory().CreateReadyToRun(engineParameters);

Assert.Equal(1, timesGlobalSetupCalled);
Assert.Equal(1, timesIterationSetupCalled);
Assert.Equal(1 + 1, timesIterationSetupCalled); // 1x for Idle, 1x for Target
Assert.Equal(1, timesBenchmarkCalled);
Assert.Equal(1, timesIdleCalled);
Assert.Equal(1, timesIterationCleanupCalled);
Assert.Equal(1 + 1, timesIterationCleanupCalled); // 1x for Idle, 1x for Target
Assert.Equal(0, timesGlobalCleanupCalled); // cleanup is called as part of dispode

Assert.Equal(1, engine.TargetJob.Run.InvocationCount); // call the benchmark once per iteration
Expand Down Expand Up @@ -80,10 +80,10 @@ public void NonVeryTimeConsumingBenchmarksAreExecutedMoreThanOncePerIterationWit
var engine = new EngineFactory().CreateReadyToRun(engineParameters);

Assert.Equal(1, timesGlobalSetupCalled);
Assert.Equal(2, timesIterationSetupCalled); // once for single and & once for 16
Assert.Equal((1+1) * (1+1), timesIterationSetupCalled); // (once for single and & once for 16) x (1x for Idle + 1x for Target)
Assert.Equal(1 + 16, timesBenchmarkCalled);
Assert.Equal(1 + 16, timesIdleCalled);
Assert.Equal(2, timesIterationCleanupCalled); // once for single and & once for 16
Assert.Equal((1+1) * (1+1), timesIterationCleanupCalled); // (once for single and & once for 16) x (1x for Idle + 1x for Target)
Assert.Equal(0, timesGlobalCleanupCalled);

Assert.False(engine.TargetJob.Run.HasValue(RunMode.InvocationCountCharacteristic));
Expand Down

0 comments on commit c1d8ac6

Please sign in to comment.