13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief CPU warm-up utility, used to counteract CPU throttling.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuCPUWarmup.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deDefs.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deClock.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <algorithm>
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace warmupCPUInternal
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvolatile Dummy g_dummy;
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float floatMedian (const T (&v)[Size])
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	T temp[Size];
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < Size; i++)
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		temp[i] = v[i];
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::sort(DE_ARRAY_BEGIN(temp), DE_ARRAY_END(temp));
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return Size % 2 == 0
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   ? 0.5f * ((float)temp[Size/2-1] + (float)temp[Size/2])
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   : (float)temp[Size/2];
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T, int Size>
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float floatRelativeMedianAbsoluteDeviation (const T (&v)[Size])
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const float		median = floatMedian(v);
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float			absoluteDeviations[Size];
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < Size; i++)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		absoluteDeviations[i] = deFloatAbs((float)v[i] - median);
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return floatMedian(absoluteDeviations) / median;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline float dummyComputation (float initial, int numIterations)
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	a = initial;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		b = 123;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int i = 0; i < numIterations; i++)
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Arbitrary computations.
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int j = 0; j < 4; j++)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			a = deFloatCos(a + (float)b);
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			b = (b + 63) % 107 + de::abs((int)(a*10.0f));
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return a + (float)b;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid warmupCPU (void)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	float	dummy				= *warmupCPUInternal::g_dummy.m_v;
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int		computationSize		= 1;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Do a rough calibration for computationSize to get dummyComputation's running time above a certain threshold.
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (computationSize < 1<<30) // \note This condition is unlikely to be met. The "real" loop exit is the break below.
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float		singleMeasurementThreshold	= 10000.0f;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int		numMeasurements				= 3;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deInt64			times[numMeasurements];
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int i = 0; i < numMeasurements; i++)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64 startTime = deGetMicroseconds();
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dummy = dummyComputation(dummy, computationSize);
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			times[i] = (deInt64)(deGetMicroseconds() - startTime);
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (floatMedian(times) >= singleMeasurementThreshold)
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		computationSize *= 2;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Do dummyComputations until running time seems stable enough.
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			maxNumMeasurements							= 50;
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int			numConsecutiveMeasurementsRequired			= 5;
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const float			relativeMedianAbsoluteDeviationThreshold	= 0.05f;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deInt64				latestTimes[numConsecutiveMeasurementsRequired];
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int measurementNdx = 0;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 measurementNdx < maxNumMeasurements &&
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 (measurementNdx < numConsecutiveMeasurementsRequired ||
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  floatRelativeMedianAbsoluteDeviation(latestTimes) > relativeMedianAbsoluteDeviationThreshold);
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 measurementNdx++)
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			const deUint64 startTime = deGetMicroseconds();
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			dummy = dummyComputation(dummy, computationSize);
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			latestTimes[measurementNdx % numConsecutiveMeasurementsRequired] = (deInt64)(deGetMicroseconds() - startTime);
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*warmupCPUInternal::g_dummy.m_v = dummy;
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu
135