4.3.3.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);
size_t nbCol(nbElement*PLIB_VECTOR_SIZE_FLOAT*2lu);
|
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
|
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
2
3
4
5
|
tmpU1 = tmpVecInU.getData();
tmpU2 = tmpVecInV.getData();
tmpV1 = tmpVecOutU.getData();
tmpV2 = tmpVecOutV.getData();
float * ptrVecMatStencil = vecMatDeltaSquare.getData();
|
Et nous mettons à jour la taille des matrices en conséquence :
1
|
size_t nbVecRow(tmpVecInV.getFullNbRow()), nbVecCol(tmpVecInV.getNbCol());
|
Finalement nous appellons la fonction qui évaluera les performances de notre kernel :
1
2
3
4
|
micro_benchmarkAutoNsPrint("evaluate GrayScott reaction, intrinsics", nbElement, grayscott_propagation,
tmpU2, tmpV2, tmpU1, tmpV1, nbVecRow, nbVecCol,
ptrVecMatStencil, nbStencilRow, nbStencilCol,
diffudionRateU, diffusionRateV, feedRate, killRate, dt);
|
Enfin, nous finissons cette fonction :