92280002291cf66835fc1da41968959f794755ec
[GPU.git] / Fractal.cu
1 #include "Fractal.h"\r
2 \r
3 #include <iostream>\r
4 #include <sstream>\r
5 #include <assert.h>\r
6 using namespace std;\r
7 \r
8 #include <omp.h>\r
9 \r
10 #include "FractalDevice.h"\r
11 #include "Device.h"\r
12 \r
13 Fractal::Fractal(int w, int h) :\r
14         w(w), h(h),\r
15         dg(8, 8, 1),\r
16         db(16, 16, 1)\r
17     {\r
18     //print(dg, db);\r
19     Device::assertDim(dg, db);\r
20     }\r
21 \r
22 Fractal::~Fractal()\r
23     {\r
24     delete this->ptrDomaineMathInit;\r
25     }\r
26 \r
27 /**\r
28  * Override\r
29  */\r
30 int Fractal::getW()\r
31     {\r
32     return this->w;\r
33     }\r
34 \r
35 /**\r
36  * Override\r
37  */\r
38 int Fractal::getH()\r
39     {\r
40     return this->h;\r
41     }\r
42 \r
43 DomaineMath* Fractal::getDomaineMathInit()\r
44     {\r
45     return this->ptrDomaineMathInit;\r
46     }\r
47 \r
48 /////\r
49 \r
50 FractalMandelbrot::FractalMandelbrot(int w, int h, int dn, bool multiGPU) :\r
51         Fractal(w, h),\r
52         variateurAnimationN(IntervalI(10, 100), dn),\r
53         n(0),\r
54         multiGPU(multiGPU)\r
55     {\r
56     // Constuit le titre dynamiquement.\r
57     ostringstream titleStream;\r
58     titleStream << "Fractal Mandelbrot (multi-GPU " << (this->multiGPU ? "activated" : "not activated") << ")";\r
59     this->title = titleStream.str();\r
60 \r
61     this->ptrDomaineMathInit = new DomaineMath(-2, -1.3, 0.8, 1.3);\r
62 \r
63     if (this->multiGPU)\r
64         {\r
65         const int nbDevice = Device::getDeviceCount();\r
66 \r
67         this->hDevices = h / nbDevice;\r
68         this->hFirstDevice = h - ((nbDevice - 1) * this->hDevices);\r
69 \r
70         // Allocation de la mémoire sur chaque GPU (sauf le premier pour lequel 'ptrDevPixels' est automatiquement alloué à l'appel de 'runGPU(..)').\r
71         this->ptrDevPixelsMultGPU = new uchar4*[nbDevice - 1];\r
72         for (int i = 0; i < nbDevice - 1; ++i)\r
73             {\r
74             HANDLE_ERROR(cudaSetDevice(i + 1));\r
75             HANDLE_ERROR(cudaMalloc(&this->ptrDevPixelsMultGPU[i], sizeof(uchar4) * w * this->hDevices));\r
76             }\r
77 \r
78         HANDLE_ERROR(cudaSetDevice(0));\r
79         }\r
80     }\r
81 \r
82 FractalMandelbrot::~FractalMandelbrot()\r
83     {\r
84     if (this->multiGPU)\r
85         {\r
86         const int nbDevice = Device::getDeviceCount();\r
87 \r
88         for (int i = 0; i < nbDevice - 1; ++i)\r
89             {\r
90             HANDLE_ERROR(cudaSetDevice(i + 1));\r
91             HANDLE_ERROR(cudaFree(this->ptrDevPixelsMultGPU[i]));\r
92             }\r
93 \r
94         HANDLE_ERROR(cudaSetDevice(0));\r
95         delete[] this->ptrDevPixelsMultGPU;\r
96         }\r
97 \r
98     cout << "OKOKOKOK" << endl;\r
99     }\r
100 \r
101 void FractalMandelbrot::animationStep()\r
102     {\r
103     this->n = this->variateurAnimationN.varierAndGet();\r
104     }\r
105 \r
106 vector<string> FractalMandelbrot::getNames()\r
107     {\r
108     vector<string> name;\r
109     name.push_back("n = ");\r
110     return name;\r
111     }\r
112 \r
113 void FractalMandelbrot::getValues(float* values)\r
114     {\r
115     values[0] = float(this->n);\r
116     }\r
117 \r
118 string FractalMandelbrot::getTitle()\r
119     {\r
120     return this->title;\r
121     }\r
122 \r
123 void FractalMandelbrot::runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath)\r
124     {\r
125 \r
126     if (this->multiGPU)\r
127         {\r
128         HANDLE_ERROR(cudaSetDevice(0));\r
129         fractalMandelbrot<<<dg,db>>>(ptrDevPixels, this->w, 0, this->hFirstDevice, domaineMath, this->n);\r
130 \r
131         const int nbDevice = Device::getDeviceCount();\r
132 \r
133         // Rend chaque tranche par un GPU différent puis copie chaque tranche dans la mémoire du premier GPU.\r
134         #pragma omp parallel for\r
135         for (int i = 0; i < nbDevice - 1; ++i)\r
136             {\r
137             HANDLE_ERROR(cudaSetDevice(i + 1));\r
138             fractalMandelbrot<<<dg,db>>>(this->ptrDevPixelsMultGPU[i], this->w, i * this->hDevices + this->hFirstDevice, (i + 1) * this->hDevices + this->hFirstDevice, domaineMath, this->n);\r
139             HANDLE_ERROR(cudaMemcpy(ptrDevPixels + this->w * this->hFirstDevice + i * this->w * this->hDevices, this->ptrDevPixelsMultGPU[i], sizeof(uchar4) * this->w * this->hDevices, cudaMemcpyDeviceToDevice));\r
140             }\r
141 \r
142         HANDLE_ERROR(cudaSetDevice(0));\r
143         }\r
144     else\r
145         {\r
146         fractalMandelbrot<<<dg,db>>>(ptrDevPixels, this->w, 0, this->h, domaineMath, this->n);\r
147         }\r
148     }\r
149 \r
150 /////\r
151 \r
152 FractalJulia::FractalJulia(int w, int h, int n, float z_r_min, float z_r_max, float z_i_min, float z_i_max) :\r
153         Fractal(w, h),\r
154         n(n),\r
155         z_r(z_r_min),\r
156         z_i(z_i_min),\r
157         variateurAnimationR(IntervalF(-0.8, -0.7), 0.0005),\r
158         variateurAnimationI(IntervalF(-0.3, 0.3), 0.0004)\r
159     {\r
160     this->ptrDomaineMathInit = new DomaineMath(-1.7, -1.4, 1.7, 1.4);\r
161     }\r
162 \r
163 void FractalJulia::animationStep()\r
164     {\r
165     this->z_r = this->variateurAnimationR.varierAndGet();\r
166     this->z_i = this->variateurAnimationI.varierAndGet();\r
167     }\r
168 \r
169 vector<string> FractalJulia::getNames()\r
170     {\r
171     vector<string> name;\r
172     name.push_back("z_r = ");\r
173     name.push_back("z_i = ");\r
174     return name;\r
175     }\r
176 \r
177 void FractalJulia::getValues(float* values)\r
178     {\r
179     values[0] = this->z_r;\r
180     values[1] = this->z_i;\r
181     }\r
182 \r
183 string FractalJulia::getTitle()\r
184     {\r
185     return "Fractal Julia";\r
186     }\r
187 \r
188 void FractalJulia::runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath)\r
189     {\r
190     fractalJulia<<<dg,db>>>(ptrDevPixels, this->w, this->h, domaineMath, this->n, this->z_r, this->z_i);\r
191     }\r
192 \r