Skip to content

Commit

Permalink
[NeoMathEngine] speed-up VectorBenchmarkTest
Browse files Browse the repository at this point in the history
Signed-off-by: Kirill Golikov <[email protected]>
  • Loading branch information
favorart committed Oct 18, 2023
1 parent 84284be commit 4612399
Showing 1 changed file with 119 additions and 77 deletions.
196 changes: 119 additions & 77 deletions NeoMathEngine/test/src/inference/VectorBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,76 +35,118 @@ static const char* vectorFunctionsNames[]{
"VectorHSwish"
};

static void vectorBenchmark( int function, int testCount, int vectorSize, const CInterval& vectorValuesInterval,
int seed, IPerformanceCounters& counters, std::ofstream& fout )
//------------------------------------------------------------------------------------------------------------

class VectorBenchmarkParams final {
public:
int Function = -2;
int TestCount = -1;
int VectorSize = -1;
IPerformanceCounters* Counters = nullptr;
std::ofstream FOut{};

VectorBenchmarkParams( int function, int testCount, int vectorSize,
const CInterval& valuesInterval, int seed );
~VectorBenchmarkParams() { delete Counters; }

void SetNextSeedForFunction( int function, int seed );

CFloatWrapper GetInputBuffer() { return CFloatWrapper( MathEngine(), input.data(), VectorSize ); }
CFloatWrapper GetSecondBuffer() { return CFloatWrapper( MathEngine(), second.data(), VectorSize ); }
CFloatWrapper GetResultBuffer() { return CFloatWrapper( MathEngine(), result.data(), VectorSize ); }
CFloatWrapper GetZeroVal() { float zero = 0; return CFloatWrapper( MathEngine(), &zero, 1 ); }
CFloatWrapper GetMulVal() {
float multiplier = static_cast<float>( random.Uniform( 1, valuesInterval.End ) );
return CFloatWrapper( MathEngine(), &multiplier, 1 );
}

private:
const CInterval& valuesInterval;
CRandom random;

std::vector<float> input;
std::vector<float> second;
std::vector<float> result;
};

VectorBenchmarkParams::VectorBenchmarkParams( int function, int testCount, int vectorSize,
const CInterval& valuesInterval, int seed ) :
Function( function ),
TestCount( testCount ),
VectorSize( vectorSize ),
Counters( MathEngine().CreatePerformanceCounters() ),
FOut( std::ofstream( "VectorBenchmarkTest.csv", std::ios::app ) ),
valuesInterval( valuesInterval )
{
FOut << "\n---------------------------" << std::endl;
input.resize( vectorSize );
second.resize( vectorSize );
result.resize( vectorSize );
SetNextSeedForFunction( function, seed );
}

void VectorBenchmarkParams::SetNextSeedForFunction( int function, int seed )
{
CRandom random( seed );
CREATE_FILL_FLOAT_ARRAY( input, vectorValuesInterval.Begin, vectorValuesInterval.End, vectorSize, random )
CREATE_FILL_FLOAT_ARRAY( second, vectorValuesInterval.Begin, vectorValuesInterval.End, vectorSize, random )
std::vector<float> result( vectorSize, 0 );

float zero = 0;
float multiplier = static_cast<float>( random.Uniform( 1, vectorValuesInterval.End ) );
CFloatWrapper zeroVal( MathEngine(), &zero, 1 );
CFloatWrapper mulVal( MathEngine(), &multiplier, 1 );
ASSERT_EXPR( ( ( CConstFloatHandle )mulVal ).GetValueAt( 0 ) > 0 );

if( function == -1 ) { // warm-up
return;
Function = function;
random = CRandom( seed );
for( int i = 0; i < VectorSize; ++i ) {
input[i] = static_cast<float>( random.Uniform( valuesInterval.Begin, valuesInterval.End ) );
second[i] = static_cast<float>( random.Uniform( valuesInterval.Begin, valuesInterval.End ) );
result[i] = 0;
}
}

//------------------------------------------------------------------------------------------------------------

static double vectorBenchmark( VectorBenchmarkParams& params )
{
CFloatWrapper zeroVal = params.GetInputBuffer();
CFloatWrapper mulVal = params.GetMulVal();
CConstFloatHandle mulHandle = mulVal;
ASSERT_EXPR( mulHandle.GetValueAt( 0 ) > 0 );

CFloatWrapper input = params.GetInputBuffer();
CFloatWrapper second = params.GetSecondBuffer();
CFloatWrapper result = params.GetResultBuffer();
const int vectorSize = params.VectorSize;

if( params.Function == -1 ) { // warm-up
MathEngine().VectorCopy( result, input, vectorSize );
MathEngine().VectorFill( result, vectorSize, mulVal );
MathEngine().VectorAdd( input, second, result, vectorSize );
MathEngine().VectorAddValue( input, result, vectorSize, mulVal );
MathEngine().VectorMultiply( input, second, vectorSize, mulVal );
MathEngine().VectorEltwiseMultiply( input, second, result, vectorSize );
MathEngine().VectorEltwiseMultiplyAdd( input, second, result, vectorSize );
MathEngine().VectorReLU( input, result, vectorSize, zeroVal ); //Threshold == 0
MathEngine().VectorReLU( input, result, vectorSize, mulVal ); //Threshold > 0
MathEngine().VectorHSwish( input, result, vectorSize );
return 0;
}

counters.Synchronise();

for( int i = 0; i < testCount; ++i ) {
switch( function ) {
case 0:
MathEngine().VectorCopy( CARRAY_FLOAT_WRAPPER( result ), CARRAY_FLOAT_WRAPPER( input ), vectorSize );
break;
case 1:
MathEngine().VectorFill( CARRAY_FLOAT_WRAPPER( result ), vectorSize, mulVal );
break;
case 2:
MathEngine().VectorAdd( CARRAY_FLOAT_WRAPPER( input ), CARRAY_FLOAT_WRAPPER( second ),
CARRAY_FLOAT_WRAPPER( result ), vectorSize );
break;
case 3:
MathEngine().VectorAddValue( CARRAY_FLOAT_WRAPPER( input ), CARRAY_FLOAT_WRAPPER( result ),
vectorSize, mulVal );
break;
case 4:
MathEngine().VectorMultiply( CARRAY_FLOAT_WRAPPER( input ),
CARRAY_FLOAT_WRAPPER( second ), vectorSize, mulVal );
break;
case 5:
MathEngine().VectorEltwiseMultiply( CARRAY_FLOAT_WRAPPER( input ),
CARRAY_FLOAT_WRAPPER( second ), CARRAY_FLOAT_WRAPPER( result ), vectorSize );
break;
case 6:
MathEngine().VectorEltwiseMultiplyAdd( CARRAY_FLOAT_WRAPPER( input ),
CARRAY_FLOAT_WRAPPER( second ), CARRAY_FLOAT_WRAPPER( result ), vectorSize );
break;
case 7:
MathEngine().VectorReLU( CARRAY_FLOAT_WRAPPER( input ), CARRAY_FLOAT_WRAPPER( result ),
vectorSize, zeroVal ); //Threshold == 0
break;
case 8:
MathEngine().VectorReLU( CARRAY_FLOAT_WRAPPER( input ), CARRAY_FLOAT_WRAPPER( result ),
vectorSize, mulVal ); //Threshold > 0
break;
case 9:
MathEngine().VectorHSwish( CARRAY_FLOAT_WRAPPER( input ), CARRAY_FLOAT_WRAPPER( result ),
vectorSize );
break;
params.Counters->Synchronise();

for( int i = 0; i < params.TestCount; ++i ) {
switch( params.Function ) {
case 0: MathEngine().VectorCopy( result, input, vectorSize ); break;
case 1: MathEngine().VectorFill( result, vectorSize, mulVal ); break;
case 2: MathEngine().VectorAdd( input, second, result, vectorSize ); break;
case 3: MathEngine().VectorAddValue( input, result, vectorSize, mulVal ); break;
case 4: MathEngine().VectorMultiply( input, second, vectorSize, mulVal ); break;
case 5: MathEngine().VectorEltwiseMultiply( input, second, result, vectorSize ); break;
case 6: MathEngine().VectorEltwiseMultiplyAdd( input, second, result, vectorSize ); break;
case 7: MathEngine().VectorReLU( input, result, vectorSize, zeroVal ); break; //Threshold == 0
case 8: MathEngine().VectorReLU( input, result, vectorSize, mulVal ); break; //Threshold > 0
case 9: MathEngine().VectorHSwish( input, result, vectorSize ); break;
default:
ASSERT_EXPR( false );
}
}

counters.Synchronise();
const double time = double( counters[0].Value ) / 1000000 / testCount; // average time in milliseconds

GTEST_LOG_( INFO ) << vectorFunctionsNames[function] << ", " << time;
fout << vectorFunctionsNames[function] << "," << time << "\n";
params.Counters->Synchronise();
const double time = double( ( *params.Counters )[0].Value ) / 1000000 / params.TestCount; // average time in milliseconds
params.FOut << time << ",";
return time;
}

} // namespace NeoMLTest
Expand All @@ -129,34 +171,34 @@ INSTANTIATE_TEST_CASE_P( CMathEngineVectorBenchmarkTestInstantiation, CMathEngin
"VectorValues = (-10..10);"
),
CTestParams(
"TestCount = 100000;"
"TestCount = 1000;"
"RepeatCount = 10;"
"VectorSize = 11796480;"
"VectorSize = 1179648;"
"VectorValues = (-1..1);"
)
)
);

TEST_P( CMathEngineVectorBenchmarkTest, DISABLED_Random )
{
CTestParams params = GetParam();

const int testCount = params.GetValue<int>( "TestCount" );
const int repeatCount = params.GetValue<int>( "RepeatCount" );
const int vectorSize = params.GetValue<int>( "VectorSize" );
const CInterval vectorValuesInterval = params.GetInterval( "VectorValues" );
CTestParams testParams = GetParam();
const int testCount = testParams.GetValue<int>( "TestCount" );
const int repeatCount = testParams.GetValue<int>( "RepeatCount" );
const int vectorSize = testParams.GetValue<int>( "VectorSize" );
const CInterval valuesInterval = testParams.GetInterval( "VectorValues" );

IPerformanceCounters* counters = MathEngine().CreatePerformanceCounters();
std::ofstream fout( "VectorBenchmarkTest.csv", std::ios::app );
fout << "---------------------------\n";

vectorBenchmark( /*warm-up*/-1, testCount, vectorSize, vectorValuesInterval, 282, *counters, fout);
VectorBenchmarkParams params( /*warm-up*/-1, testCount, vectorSize, valuesInterval, 282 );
vectorBenchmark( params );

for( int function = 0; function < 10; ++function ) {
params.FOut << std::endl << vectorFunctionsNames[function] << ",";

double timeSum = 0;
for( int test = 0; test < repeatCount; ++test ) {
const int seed = 282 + test * 10000 + test % 3;
vectorBenchmark( function, testCount, vectorSize, vectorValuesInterval, seed, *counters, fout );
params.SetNextSeedForFunction( function, seed );
timeSum += vectorBenchmark( params );
}
GTEST_LOG_( INFO ) << vectorFunctionsNames[function] << "\t" << timeSum;
}
delete counters;
}

0 comments on commit 4612399

Please sign in to comment.