#pragma once
#ifndef _STATISTICALTIMER_GPU_H_
#define _STATISTICALTIMER_GPU_H_
#include <iosfwd>
#include <vector>
#include <algorithm>
#include <cmath>
#include "statisticalTimer.h"
#include "../library/plan.h"
struct StatData
{
cl_kernel kernel;
cl_ulong deltaNanoSec;
double doubleNanoSec;
size_t batchSize;
clfftDim dim;
clfftPlanHandle plHandle;
clfftPlanHandle planX;
clfftPlanHandle planY;
clfftPlanHandle planZ;
clfftPlanHandle planTX;
clfftPlanHandle planTY;
clfftPlanHandle planTZ;
clfftPlanHandle planRCcopy;
clfftPlanHandle planCopy;
clfftGenerators gen;
std::vector< size_t > lengths;
std::vector< size_t > inStride;
std::vector< size_t > outStride;
size_t iDist;
size_t oDist;
clfftResultLocation placeness;
std::vector< size_t > enqueueLocalWorkSize;
std::vector< size_t > enqueueWorkSize;
std::vector< cl_event > outEvents;
StatData( ): deltaNanoSec( 0 )
{}
StatData( clfftPlanHandle id, FFTPlan* plan, cl_kernel kern, cl_uint nEv, cl_event* Ev,
const std::vector< size_t >& gWorkSize, const std::vector< size_t >& lWorkSize):
deltaNanoSec( 0 ), kernel( kern ), batchSize( plan->batchsize ), dim( plan->dim ),
plHandle( id ), planX( plan->planX ), planY( plan->planY ), planZ( plan->planZ ),
planTX( plan->planTX ), planTY( plan->planTY ), planTZ( plan->planTZ ),
planRCcopy( plan->planRCcopy ), planCopy( plan->planCopy ), gen(plan->gen),
inStride( plan->inStride ), outStride( plan->outStride ), iDist( plan->iDist ), oDist( plan->oDist ),
lengths( plan->length ), enqueueWorkSize( gWorkSize ), enqueueLocalWorkSize( lWorkSize ), placeness( plan->placeness )
{
for( cl_uint e = 0; e < nEv; ++e )
{
outEvents.push_back( Ev[ e ] );
}
}
double calcFlops( )
{
size_t fftLength = 0;
size_t dimIndex = 0;
if( dim == CLFFT_1D )
{
fftLength = lengths.at( 0 );
dimIndex = 1;
}
else if( dim == CLFFT_2D )
{
fftLength = lengths.at( 0 ) * lengths.at( 1 );
dimIndex = 2;
}
else if( dim == CLFFT_3D )
{
fftLength = lengths.at( 0 ) * lengths.at( 1 ) * lengths.at( 2 );
dimIndex = 3;
}
size_t cumulativeBatch = 1;
for( ; dimIndex < lengths.size(); ++dimIndex )
{
cumulativeBatch *= std::max< size_t >( 1, lengths[ dimIndex ] );
}
cumulativeBatch *= batchSize;
double flops = cumulativeBatch * 5 * fftLength * ( log( static_cast< double >( fftLength ) ) / log( 2.0 ) );
return flops;
}
};
bool operator<( const StatData& lhs, const StatData& rhs);
class GpuStatTimer : public baseStatTimer
{
typedef std::vector< StatData > StatDataVec;
typedef std::vector< StatDataVec > PerEnqueueVec;
std::vector< PerEnqueueVec > timerData;
typedef std::pair< std::string, cl_uint > idPair;
typedef std::vector< idPair > idVector;
idVector labelID;
size_t currSample, currRecord;
StatDataVec::size_type nEvents, nSamples;
size_t currID;
GpuStatTimer( );
~GpuStatTimer( );
GpuStatTimer( const GpuStatTimer& );
GpuStatTimer& operator=( const GpuStatTimer& );
friend std::ostream& operator<<( std::ostream& os, const GpuStatTimer& s );
std::vector< StatData > getMean( size_t id );
std::vector< StatData > getVariance( size_t id );
std::vector< StatData > getStdDev( size_t id );
std::vector< StatData > getAverageTime( size_t id );
std::vector< StatData > getMinimumTime( size_t id );
void queryOpenCL( size_t id );
void ReleaseEvents();
public:
static GpuStatTimer& getInstance( );
void Start( size_t id );
void Stop( size_t id );
virtual void AddSample( clfftPlanHandle plHandle, FFTPlan* plan, cl_kernel kern, cl_uint numQueuesAndEvents, cl_event* ev,
const std::vector< size_t >& gWorkSize, const std::vector< size_t >& lWorkSize );
void Clear( );
void Reset( );
void Reserve( size_t nEvents, size_t nSamples );
size_t getUniqueID( const std::string& label, cl_uint groupID );
void setNormalize( bool norm );
void Print( );
size_t pruneOutliers( cl_double multiple );
std::vector< size_t > pruneOutliers( size_t id , cl_double multiple );
};
#endif