Début du TP convolution. Pour l'instant uniquement lecture d'une vidéo.
[GPU.git] / WCudaMSE / Student_Cuda_Image / src / cpp / core / 02_Mandelbrot_Julia / moo / host / Fractal.cu
index 88a225b..9228000 100755 (executable)
@@ -1,20 +1,19 @@
+#include "Fractal.h"\r
+\r
 #include <iostream>\r
+#include <sstream>\r
 #include <assert.h>\r
+using namespace std;\r
 \r
-#include "Fractal.h"\r
-#include "Device.h"\r
-\r
-using std::cout;\r
-using std::endl;\r
+#include <omp.h>\r
 \r
-extern __global__ void fractalMandelbrot(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n);\r
-extern __global__ void fractalJulia(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n, float c_r, float c_i);\r
+#include "FractalDevice.h"\r
+#include "Device.h"\r
 \r
-Fractal::Fractal(int w, int h)\r
-    : w(w), h(h),\r
-      dg(8, 8, 1),\r
-      db(16, 16, 1),\r
-      title("Fractal Cuda")\r
+Fractal::Fractal(int w, int h) :\r
+        w(w), h(h),\r
+        dg(8, 8, 1),\r
+        db(16, 16, 1)\r
     {\r
     //print(dg, db);\r
     Device::assertDim(dg, db);\r
@@ -46,20 +45,57 @@ DomaineMath* Fractal::getDomaineMathInit()
     return this->ptrDomaineMathInit;\r
     }\r
 \r
-/**\r
- * Override\r
- */\r
-string Fractal::getTitle()\r
-    {\r
-    return this->title;\r
-    }\r
-\r
 /////\r
 \r
-FractalMandelbrot::FractalMandelbrot(int w, int h, float dn)\r
-    : Fractal(w, h), variateurAnimationN(IntervalF(30, 100), dn)\r
+FractalMandelbrot::FractalMandelbrot(int w, int h, int dn, bool multiGPU) :\r
+        Fractal(w, h),\r
+        variateurAnimationN(IntervalI(10, 100), dn),\r
+        n(0),\r
+        multiGPU(multiGPU)\r
     {\r
+    // Constuit le titre dynamiquement.\r
+    ostringstream titleStream;\r
+    titleStream << "Fractal Mandelbrot (multi-GPU " << (this->multiGPU ? "activated" : "not activated") << ")";\r
+    this->title = titleStream.str();\r
+\r
     this->ptrDomaineMathInit = new DomaineMath(-2, -1.3, 0.8, 1.3);\r
+\r
+    if (this->multiGPU)\r
+        {\r
+        const int nbDevice = Device::getDeviceCount();\r
+\r
+        this->hDevices = h / nbDevice;\r
+        this->hFirstDevice = h - ((nbDevice - 1) * this->hDevices);\r
+\r
+        // Allocation de la mémoire sur chaque GPU (sauf le premier pour lequel 'ptrDevPixels' est automatiquement alloué à l'appel de 'runGPU(..)').\r
+        this->ptrDevPixelsMultGPU = new uchar4*[nbDevice - 1];\r
+        for (int i = 0; i < nbDevice - 1; ++i)\r
+            {\r
+            HANDLE_ERROR(cudaSetDevice(i + 1));\r
+            HANDLE_ERROR(cudaMalloc(&this->ptrDevPixelsMultGPU[i], sizeof(uchar4) * w * this->hDevices));\r
+            }\r
+\r
+        HANDLE_ERROR(cudaSetDevice(0));\r
+        }\r
+    }\r
+\r
+FractalMandelbrot::~FractalMandelbrot()\r
+    {\r
+    if (this->multiGPU)\r
+        {\r
+        const int nbDevice = Device::getDeviceCount();\r
+\r
+        for (int i = 0; i < nbDevice - 1; ++i)\r
+            {\r
+            HANDLE_ERROR(cudaSetDevice(i + 1));\r
+            HANDLE_ERROR(cudaFree(this->ptrDevPixelsMultGPU[i]));\r
+            }\r
+\r
+        HANDLE_ERROR(cudaSetDevice(0));\r
+        delete[] this->ptrDevPixelsMultGPU;\r
+        }\r
+\r
+    cout << "OKOKOKOK" << endl;\r
     }\r
 \r
 void FractalMandelbrot::animationStep()\r
@@ -67,20 +103,59 @@ void FractalMandelbrot::animationStep()
     this->n = this->variateurAnimationN.varierAndGet();\r
     }\r
 \r
-float FractalMandelbrot::getT()\r
+vector<string> FractalMandelbrot::getNames()\r
     {\r
-    return this->n;\r
+    vector<string> name;\r
+    name.push_back("n = ");\r
+    return name;\r
+    }\r
+\r
+void FractalMandelbrot::getValues(float* values)\r
+    {\r
+    values[0] = float(this->n);\r
+    }\r
+\r
+string FractalMandelbrot::getTitle()\r
+    {\r
+    return this->title;\r
     }\r
 \r
 void FractalMandelbrot::runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath)\r
     {\r
-    fractalMandelbrot<<<dg,db>>>(ptrDevPixels, this->w, this->h, domaineMath, static_cast<int>(this->n));\r
+\r
+    if (this->multiGPU)\r
+        {\r
+        HANDLE_ERROR(cudaSetDevice(0));\r
+        fractalMandelbrot<<<dg,db>>>(ptrDevPixels, this->w, 0, this->hFirstDevice, domaineMath, this->n);\r
+\r
+        const int nbDevice = Device::getDeviceCount();\r
+\r
+        // Rend chaque tranche par un GPU différent puis copie chaque tranche dans la mémoire du premier GPU.\r
+        #pragma omp parallel for\r
+        for (int i = 0; i < nbDevice - 1; ++i)\r
+            {\r
+            HANDLE_ERROR(cudaSetDevice(i + 1));\r
+            fractalMandelbrot<<<dg,db>>>(this->ptrDevPixelsMultGPU[i], this->w, i * this->hDevices + this->hFirstDevice, (i + 1) * this->hDevices + this->hFirstDevice, domaineMath, this->n);\r
+            HANDLE_ERROR(cudaMemcpy(ptrDevPixels + this->w * this->hFirstDevice + i * this->w * this->hDevices, this->ptrDevPixelsMultGPU[i], sizeof(uchar4) * this->w * this->hDevices, cudaMemcpyDeviceToDevice));\r
+            }\r
+\r
+        HANDLE_ERROR(cudaSetDevice(0));\r
+        }\r
+    else\r
+        {\r
+        fractalMandelbrot<<<dg,db>>>(ptrDevPixels, this->w, 0, this->h, domaineMath, this->n);\r
+        }\r
     }\r
 \r
 /////\r
 \r
-FractalJulia::FractalJulia(int w, int h, float dn, float z_r_min, float z_r_max, float z_i_min, float z_i_max)\r
-    : Fractal(w, h), z_r(z_r_min), z_i(z_i_min), variateurAnimationR(IntervalF(-0.8, -0.7), 0.0005), variateurAnimationI(IntervalF(-0.3, 0.3/*0.15*/), 0.0004)\r
+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
+        Fractal(w, h),\r
+        n(n),\r
+        z_r(z_r_min),\r
+        z_i(z_i_min),\r
+        variateurAnimationR(IntervalF(-0.8, -0.7), 0.0005),\r
+        variateurAnimationI(IntervalF(-0.3, 0.3), 0.0004)\r
     {\r
     this->ptrDomaineMathInit = new DomaineMath(-1.7, -1.4, 1.7, 1.4);\r
     }\r
@@ -91,13 +166,27 @@ void FractalJulia::animationStep()
     this->z_i = this->variateurAnimationI.varierAndGet();\r
     }\r
 \r
-float FractalJulia::getT()\r
+vector<string> FractalJulia::getNames()\r
+    {\r
+    vector<string> name;\r
+    name.push_back("z_r = ");\r
+    name.push_back("z_i = ");\r
+    return name;\r
+    }\r
+\r
+void FractalJulia::getValues(float* values)\r
+    {\r
+    values[0] = this->z_r;\r
+    values[1] = this->z_i;\r
+    }\r
+\r
+string FractalJulia::getTitle()\r
     {\r
-    return this->z_r;\r
+    return "Fractal Julia";\r
     }\r
 \r
 void FractalJulia::runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath)\r
     {\r
-    fractalJulia<<<dg,db>>>(ptrDevPixels, this->w, this->h, domaineMath, 300, this->z_r, this->z_i);\r
+    fractalJulia<<<dg,db>>>(ptrDevPixels, this->w, this->h, domaineMath, this->n, this->z_r, this->z_i);\r
     }\r
 \r