5.8.7.1.3 : La fonction générale du programme


Maintenant, implémentons la fonctions générale :

1
2
3
4
5
6
7
8
9
10
11
12
13
///Simulate the images
/**	@param nbRow : number of rows of the images to be created
 * 	@param nbCol : number of columns of the images to be created
 * 	@param nbImage : number of images to be created
 * 	@param nbExtraStep : number of extra steps to be computed between images
 * 	@param nbGpuCall : number of time to call the GPU to create nbImage
 * 	@param killRate : rate of the process which converts V into P
 * 	@param feedRate : rate of the process which feeds U and drains U, V and P
 * 	@param dt : time interval between two computation
 * 	@param outputFile : name of the file to be created
 * 	@return true on succsess, false otherwise
*/
bool simulateImage(size_t nbRow, size_t nbCol, size_t nbImage, size_t nbExtraStep, size_t nbGpuCall, float killRate, float feedRate, float dt, const std::string & outputFile){	


Nous allons commencer par indiquer quelques paramètres utiles pour l'utilisateur :

1
	std::cout << "simulateImage : nbRow = " << nbRow << ", nbCol = " << nbCol << std::endl;


Initialisons le temporaire qui contiendra toutes les images simulées :

1
2
	std::vector<float> tmpImage;
	tmpImage.resize(nbImage*nbRow*nbCol);


On créé et on initialise les PTensor et les pointeurs de nos images temporaires :

1
2
3
4
	size_t paddedNbRow(nbRow + 2l), paddedNbCol(nbCol + 2l);
	
	std::vector<float> tmpInU, tmpInV, tmpOutU, tmpOutV;
	allocate_temporary(tmpInU, tmpInV, tmpOutU, tmpOutV, paddedNbRow, paddedNbCol);


On définit notre stencil 3x3 (avec éventuellement des coéfficients plus sérieux mais qui donnent des résultats moins rigolos) :

1
2
3
	long nbStencilRow(3l), nbStencilCol(3l);
	
	float diffusionRateU(0.1f), diffusionRateV(0.05f);


La déclaration de notre matrice de coéficients doit impérativement se faire avec une allocation dynamique. C'est pourquoi nous utilisons un std::vector.

1
2
3
4
5
6
7
8
	//This matrix of neigbour exchange is quite accurate but gives not so fun results
// 	std::vector<float> matDeltaSquare[] = 	{0.05f, 0.2f, 0.05f,
// 					0.2f, 0.0f, 0.2f,
// 					0.05f, 0.2f, 0.05f};
	std::vector<float> matDeltaSquare{1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, 1.0f};
	float * ptrMatDeltaSquare = matDeltaSquare.data();


Si vous utilisez ne serait-ce qu'un seul pointeur alloué statiquement, vous aurez des erreurs : invalid pointer ou for_each: failed to synchronize: cudaErrorIllegalAddress: an illegal memory access was encountered.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
	
	float * matOutV = tmpImage.data();
	float *tmpU1 = tmpInU.data(), *tmpU2 = tmpOutU.data(), *tmpV1 = tmpInV.data(), *tmpV2 = tmpOutV.data();
	std::cout << "matOutV = " << matOutV << ", tmpU1 = " << tmpU1 << ", tmpU2 = " << tmpU2 << ", tmpV1 = " << tmpV1 << ", tmpV2 = " << tmpV2 << std::endl;
        std::cout << "nbImage = " << nbImage << ", nbExtraStep = " << nbExtraStep << ", nbGpuCall = " << nbGpuCall << ", nbRow = " << nbRow << ", nbCol = " << nbCol << std::endl;
        std::cout << "paddedNbRow = " << paddedNbRow << ", paddedNbCol = " << paddedNbCol << std::endl;
        std::cout << "ptrMatDeltaSquare = " << ptrMatDeltaSquare << ", nbStencilRow = " << nbStencilRow << ", nbStencilCol = " << nbStencilCol << std::endl;
        std::cout << "diffusionRateU = " << diffusionRateU << ", diffusionRateV = " << diffusionRateV << ", feedRate = " << feedRate << ", killRate = " << killRate << ", dt = " << dt << std::endl;

	gray_scott_nvcpp(matOutV, tmpU1, tmpV1, tmpU2, tmpV2,
			nbImage, nbExtraStep - (nbExtraStep % 2lu), nbGpuCall, nbRow, nbCol, 
			paddedNbRow, paddedNbCol,
			ptrMatDeltaSquare, nbStencilRow, nbStencilCol,
			diffusionRateU, diffusionRateV, feedRate, killRate, dt);


On dit que le calcul est fini :

1
	std::cerr << "Done" << std::endl;


Ensuite, nous devons définir l'ensemble de nos images en HDF5 :

1
2
3
	MatrixHdf5 fullMat;
	fullMat.setAllDim(nbCol, nbRow);
	fullMat.resize(nbImage);


Puis insérer les résultats que nous avons obtenus :

1
2
3
	for(size_t i(0lu); i < nbImage; ++i){
		fullMat.setRow(i, matOutV + i*nbRow*nbCol);
	}


On écrit le fichier HDF5 :

1
2
	//Let's save the output file
	fullMat.write(outputFile);


On renvoie true car tout s'est bien passé et on finit la fonction :

1
2
	return true;
}