Example #1
0
        /// <returns>the time it took to run the benchmark</returns>
        private static TimeInterval Jit(Engine engine, int jitIndex, int invokeCount, int unrollFactor)
        {
            engine.Dummy1Action.Invoke();

            DeadCodeEliminationHelper.KeepAliveWithoutBoxing(engine.RunIteration(new IterationData(IterationMode.Overhead, IterationStage.Jitting, jitIndex, invokeCount, unrollFactor))); // don't forget to JIT idle

            engine.Dummy2Action.Invoke();

            var result = engine.RunIteration(new IterationData(IterationMode.Workload, IterationStage.Jitting, jitIndex, invokeCount, unrollFactor));

            engine.Dummy3Action.Invoke();

            engine.WriteLine();

            return(TimeInterval.FromNanoseconds(result.Nanoseconds));
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }