5.8.7.1.4 : La fonction principale du programme


Maintenant, implémentons la fonctions principale :

1
int main(int argc, char** argv){


On créé notre parseur d'argument avec la fonction createOptionParser définie plus tôt :

1
2
	OptionParser parser = createOptionParser();
	parser.parseArgument(argc, argv);


On récupère les arguments qui ont été passés au programme (les valeurs par défauts sont gérées automatiquement) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	const OptionMode & defaultMode = parser.getDefaultMode();
	float killRate(0.062f), feedRate(0.03f), dt(1.0f);
	size_t nbImage(10lu), nbRow(1080lu), nbCol(1920lu), nbExtraStep(34lu), nbGpuCall(1lu);;
	defaultMode.getValue(killRate, "killrate");
	defaultMode.getValue(feedRate, "feedrate");
	defaultMode.getValue(nbImage, "nbimage");
	defaultMode.getValue(nbExtraStep, "nbextrastep");
	defaultMode.getValue(nbGpuCall, "nbgpucall");
	defaultMode.getValue(nbRow, "nbrow");
	defaultMode.getValue(nbCol, "nbcol");
	defaultMode.getValue(dt, "deltat");
	
	std::string outputFile("output.h5");
	defaultMode.getValue(outputFile, "output");


On appelle notre fonction générale :

1
2
3
	std::cout << "nbImage = " << nbImage << ", nbRow = " << nbRow << ", nbCol = " << nbCol << ", nbExtraStep = " << nbExtraStep << ", nbGpuCall = " << nbGpuCall << std::endl;
        std::cout << "killRate = " << killRate << ", feedRate = " << feedRate << ", dt = " << dt << std::endl;
	bool b(simulateImage(nbRow, nbCol, nbImage, nbExtraStep, nbGpuCall, killRate, feedRate, dt, outputFile));


On retourne 0 en cas de succès et -1 en cas d'erreur :

1
	return b - 1;


On finit la fonction principale :

1
}


Le fichier main.cpp complet :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/
#include "OptionParser.h"
#include "temporary_alloc.h"
#include "gray_scott_nvcpp.h"
#include "MatrixHdf5.h"

///Create the OptionParser of this program
/**	@return OptionParser of this program
*/
OptionParser createOptionParser(){
	OptionParser parser(true, __PROGRAM_VERSION__);
	parser.setExampleLongOption("gray_scott_gpu_nvcpp_vector --killrate=0.062 --feedrate=0.03 --nbimage=100 --nbrow=1080 --nbcol=1920 --output=outputFile.h5");
	parser.setExampleShortOption("gray_scott_gpu_nvcpp_vector -k 0.062 -f 0.03 -n 100 -r 1080 -c 1920 -o outputFile.h5");
	
	float killRate(0.054f), feedRate(0.014f);
	size_t nbImage(100lu), nbRow(100lu), nbCol(200lu);
	parser.addOption("killrate", "k", killRate, "rate of the process which converts V into P");
	parser.addOption("feedrate", "f", feedRate, "rate of the process which feeds U and drains U, V and P");
	parser.addOption("nbimage", "n", nbImage, "number of images to be created");
	size_t nbExtraStep(1lu);
	parser.addOption("nbextrastep", "e", nbExtraStep, "number of extra steps to be computed between images");
	parser.addOption("nbgpucall", "g", nbExtraStep, "number of GPU calls which compute nbimage");
	
	parser.addOption("nbrow", "r", nbRow, "number of rows of the images to be created");
	parser.addOption("nbcol", "c", nbCol, "number of columns of the images to be created");
	float dt(1.0f);
	parser.addOption("deltat", "t", dt, "time interval between two computation");
	
	std::string defaultOutputFile("output.h5");
	parser.addOption("output", "o", defaultOutputFile, "Output file to be created with results");
	return parser;
}
///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){	
	std::cout << "simulateImage : nbRow = " << nbRow << ", nbCol = " << nbCol << std::endl;
	std::vector<float> tmpImage;
	tmpImage.resize(nbImage*nbRow*nbCol);
	size_t paddedNbRow(nbRow + 2l), paddedNbCol(nbCol + 2l);
	
	std::vector<float> tmpInU, tmpInV, tmpOutU, tmpOutV;
	allocate_temporary(tmpInU, tmpInV, tmpOutU, tmpOutV, paddedNbRow, paddedNbCol);
	long nbStencilRow(3l), nbStencilCol(3l);
	
	float diffusionRateU(0.1f), diffusionRateV(0.05f);
	//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();
	
	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);
	std::cerr << "Done" << std::endl;
	MatrixHdf5 fullMat;
	fullMat.setAllDim(nbCol, nbRow);
	fullMat.resize(nbImage);
	for(size_t i(0lu); i < nbImage; ++i){
		fullMat.setRow(i, matOutV + i*nbRow*nbCol);
	}
	//Let's save the output file
	fullMat.write(outputFile);
	return true;
}

int main(int argc, char** argv){
	OptionParser parser = createOptionParser();
	parser.parseArgument(argc, argv);
	const OptionMode & defaultMode = parser.getDefaultMode();
	float killRate(0.062f), feedRate(0.03f), dt(1.0f);
	size_t nbImage(10lu), nbRow(1080lu), nbCol(1920lu), nbExtraStep(34lu), nbGpuCall(1lu);;
	defaultMode.getValue(killRate, "killrate");
	defaultMode.getValue(feedRate, "feedrate");
	defaultMode.getValue(nbImage, "nbimage");
	defaultMode.getValue(nbExtraStep, "nbextrastep");
	defaultMode.getValue(nbGpuCall, "nbgpucall");
	defaultMode.getValue(nbRow, "nbrow");
	defaultMode.getValue(nbCol, "nbcol");
	defaultMode.getValue(dt, "deltat");
	
	std::string outputFile("output.h5");
	defaultMode.getValue(outputFile, "output");
	std::cout << "nbImage = " << nbImage << ", nbRow = " << nbRow << ", nbCol = " << nbCol << ", nbExtraStep = " << nbExtraStep << ", nbGpuCall = " << nbGpuCall << std::endl;
        std::cout << "killRate = " << killRate << ", feedRate = " << feedRate << ", dt = " << dt << std::endl;
	bool b(simulateImage(nbRow, nbCol, nbImage, nbExtraStep, nbGpuCall, killRate, feedRate, dt, outputFile));
	return b - 1;
}


Vous pouvez le télécharger ici.