5.2.2.1.2 : La fonction d'évaluation de performance


La fonction qui fera l'évaluation de performance de notre kernel de calcul :

1
2
3
4
///Get the number of nanoseconds per elements
/**	@param nbElement : number of elements of the tables
*/
void evaluateGrayScott(size_t nbElement){


Commençons par un petit subterfuge pour transformer le nombre d'élément nbElement à une dimension en un nombre de ligne et un nombre de colone (la macro PLIB_VECTOR_SIZE_FLOAT définit la taille d'un registre vectoriel de float) :

1
2
	size_t nbRow(nbElement*PLIB_VECTOR_SIZE_FLOAT*10lu);
	size_t nbCol(nbElement*PLIB_VECTOR_SIZE_FLOAT*2lu*10lu);


Il faut cependant mettre à jour le nouveau nombre d'éléments :

1
	nbElement = nbRow*nbCol;


Nous devons maintenant allouer nos images temporaires avec la fonction allocate_temporary que nous avons implémenté dans la section 3.1.2 :

1
2
3
	PTensor<float> tmpInU, tmpInV, tmpOutU, tmpOutV;
	float *tmpU1 = NULL, *tmpU2 = NULL, *tmpV1 = NULL, *tmpV2 = NULL;
	allocate_temporary(tmpU1, tmpU2, tmpV1, tmpV2, tmpInU, tmpInV, tmpOutU, tmpOutV, nbRow, nbCol);


Initialisons les paramètres de notre fonction de calcul :

1
2
3
	float diffudionRateU(0.1f), diffusionRateV(0.05f);
	float killRate(0.054f), feedRate(0.014f), dt(1.0f);
	long nbStencilRow(3l), nbStencilCol(3l);


Et, notre matrice de poids pour le gradient de concentration entre des cellules voisines (pour le moment ce n'est pas la peine de changer les valeurs car c'est un test de performance qui ne produit pas d'images) :

1
2
3
	float matDeltaSquare[] = 	{1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, 1.0f};


Il faut maintenant convertir nos temporaires avec des voisins classiques, en temporaires avec des voisins vectoriels. Heureusement les PTensor ont une méthode fromScalToVecNeigbhour qui le fait pour nous :

1
2
3
4
5
6
	//Let's convert these temporaries into intrinsics temporaries
	PTensor<float> tmpVecInU(AllocMode::ALIGNED), tmpVecInV(AllocMode::ALIGNED), tmpVecOutU(AllocMode::ALIGNED), tmpVecOutV(AllocMode::ALIGNED);
	tmpVecInU.fromScalToVecNeigbhour(tmpInU, PLIB_VECTOR_SIZE_FLOAT);
	tmpVecInV.fromScalToVecNeigbhour(tmpInV, PLIB_VECTOR_SIZE_FLOAT);
	tmpVecOutU.fromScalToVecNeigbhour(tmpOutU, PLIB_VECTOR_SIZE_FLOAT);
	tmpVecOutV.fromScalToVecNeigbhour(tmpOutV, PLIB_VECTOR_SIZE_FLOAT);


De la même manière, nous devons modifier la matrice de poids afin qu'elle traite des vosins vectoriels. Encore une fois, nous pouvons utiliser une fonction reshuffle_broadcastTensor qui le fait pour nous :

1
2
	PTensor<float> vecMatDeltaSquare(AllocMode::ALIGNED, nbStencilRow, nbStencilCol*PLIB_VECTOR_SIZE_FLOAT);
	reshuffle_broadcastTensor(vecMatDeltaSquare.getData(), matDeltaSquare, nbStencilRow, nbStencilCol, 0lu, PLIB_VECTOR_SIZE_FLOAT);


Nous mettons à jour les pointeurs vers les temporaires que nous utiliserons

1
	float * ptrVecMatStencil = vecMatDeltaSquare.getData();


Et nous mettons à jour la taille des matrices en conséquence :

1
2
// 	size_t nbVecRow(tmpVecInV.getFullNbRow()), nbVecCol(tmpVecInV.getNbCol());
	size_t blockSizeRow(40lu), blockSizeCol(80lu);


Nous devons également créer nos vecteur de blocs :

1
	std::vector<PBlock<float> > vecBlockOutU, vecBlockOutV, vecBlockInU, vecBlockInV;


Finalement nous appellons la fonction qui évaluera les performances de notre kernel :

1
2
3
4
5
6
	micro_benchmarkAutoNsPrint("evaluate GrayScott reaction, intrinsics block", nbElement, grayscott_propagation_block, 
					tmpVecOutU, tmpVecOutV, tmpVecInU, tmpVecInV,
					vecBlockOutU, vecBlockOutV, vecBlockInU, vecBlockInV,
					blockSizeRow, blockSizeCol,
					ptrVecMatStencil, nbStencilRow, nbStencilCol,
					diffudionRateU, diffusionRateV, feedRate, killRate, dt);


Enfin, nous finissons cette fonction :

1
}