using std::cout;\r
using std::endl;\r
\r
-__device__ void fractal(uchar4* ptrDevPixels, int w, int h, const DomaineMath& domaineMath, int n, const FractalMath& fractalMath)\r
+__device__ void fractal(uchar4* ptrDevPixels, int w, int hFrom, int hTo, const DomaineMath& domaineMath, int n, const FractalMath& fractalMath)\r
{\r
const int TID = Indice2D::tid();\r
const int NB_THREAD = Indice2D::nbThread();\r
- const int WH = w * h;\r
+ const int WH = w * (hTo - hFrom);\r
\r
uchar4 color;\r
color.z = 255; // Par défaut, l'image est opaque.\r
\r
// (i,j) domaine écran\r
// (x,y) domaine math\r
- domaineMath.toXY(pixelI, pixelJ, &x, &y); // (i,j) -> (x,y)\r
+ domaineMath.toXY(pixelI + hFrom, pixelJ, &x, &y); // (i,j) -> (x,y)\r
\r
fractalMath.colorXY(&color, x, y);\r
\r
}\r
}\r
\r
-__global__ void fractalMandelbrot(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n)\r
+__global__ void fractalMandelbrot(uchar4* ptrDevPixels, int w, int hFrom, int hTo, DomaineMath domaineMath, int n)\r
{\r
FractalMandelbrotMath fractalMath(n);\r
- fractal(ptrDevPixels, w, h, domaineMath, n, fractalMath);\r
+ fractal(ptrDevPixels, w, hFrom, hTo, domaineMath, n, fractalMath);\r
}\r
\r
__global__ void fractalJulia(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n, float c_r, float c_i)\r
{\r
FractalJuliaMath fractalMath(n, c_r, c_i);\r
- fractal(ptrDevPixels, w, h, domaineMath, n, fractalMath);\r
+ fractal(ptrDevPixels, w, 0, h, domaineMath, n, fractalMath);\r
}\r
\r
#include "DomaineMath.h"
-__global__ void fractalMandelbrot(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n);
+__global__ void fractalMandelbrot(uchar4* ptrDevPixels, int w, int hFrom, int hTo, DomaineMath domaineMath, int n);
__global__ void fractalJulia(uchar4* ptrDevPixels, int w, int h, DomaineMath domaineMath, int n, float c_r, float c_i);
#endif
#include "Fractal.h"\r
\r
#include <iostream>\r
+#include <sstream>\r
#include <assert.h>\r
using namespace std;\r
\r
+#include <omp.h>\r
+\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
+ db(16, 16, 1)\r
{\r
//print(dg, db);\r
Device::assertDim(dg, db);\r
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, int 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
+ 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
void FractalMandelbrot::animationStep()\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
values[1] = this->z_i;\r
}\r
\r
+string FractalJulia::getTitle()\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, this->n, this->z_r, this->z_i);\r
int getH() /*override*/;\r
DomaineMath* getDomaineMathInit() /*override*/;\r
\r
- string getTitle(void) /*override*/;\r
-\r
protected:\r
// Inputs\r
const int w;\r
const dim3 db;\r
\r
DomaineMath* ptrDomaineMathInit;\r
-\r
- // Outputs\r
- const string title;\r
};\r
\r
class FractalMandelbrot : public Fractal\r
{\r
public:\r
- FractalMandelbrot(int w, int h, int dn);\r
+ FractalMandelbrot(int w, int h, int dn, bool multiGPU = false);\r
void animationStep();\r
\r
std::vector<std::string> getNames();\r
void getValues(float* values);\r
\r
+ std::string getTitle();\r
+\r
private:\r
- void runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath) /*override*/;\r
+ void runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath);\r
\r
VariateurI variateurAnimationN;\r
int n;\r
+\r
+ string title;\r
+\r
+ // Utilisé uniquement dans le cadre du multi-GPU.\r
+ bool multiGPU;\r
+ uchar4** ptrDevPixelsMultGPU; // La mémoire alloué pour les GPU autres que le premier\r
+ int hFirstDevice; // Hauteur de l'image à traiter par le premier GPU.\r
+ int hDevices; // Hauteur de l'image à traiter par les autres GPU.\r
};\r
\r
class FractalJulia : public Fractal\r
std::vector<std::string> getNames();\r
void getValues(float* values);\r
\r
+ std::string getTitle();\r
+\r
private:\r
- void runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath) /*override*/;\r
+ void runGPU(uchar4* ptrDevPixels, const DomaineMath& domaineMath);\r
\r
const int n;\r
\r
#include "FractalProvider.h"\r
\r
-Fractal* MandelbrotProvider::create()\r
+Fractal* MandelbrotProvider::create(bool multiGPU)\r
{\r
int dw = 16 * 50;\r
int dh = 16 * 30;\r
\r
- return new FractalMandelbrot(dw, dh, 1);\r
+ return new FractalMandelbrot(dw, dh, 1, multiGPU);\r
}\r
\r
Fractal* JuliaProvider::create()\r
return new FractalJulia(dw, dh, 300, -0.745, -0.32, -0.09, 0.1);\r
}\r
\r
-ImageFonctionel* MandelbrotProvider::createGL()\r
+ImageFonctionel* MandelbrotProvider::createGL(bool multiGPU)\r
{\r
ColorRGB_01* ptrColorTitre = new ColorRGB_01(0, 0, 100);\r
- return new ImageFonctionel(create(), ptrColorTitre); // both ptr destroy by destructor of ImageFonctionel\r
+ return new ImageFonctionel(create(multiGPU), ptrColorTitre); // both ptr destroy by destructor of ImageFonctionel\r
}\r
\r
ImageFonctionel* JuliaProvider::createGL()\r
class MandelbrotProvider\r
{\r
public:\r
- static Fractal* create();\r
- static ImageFonctionel* createGL();\r
+ static Fractal* create(bool multiGPU);\r
+ static ImageFonctionel* createGL(bool multiGPU);\r
};\r
\r
\r
class Viewer\r
{\r
private:\r
- TOutput* ptrProvider;\r
+ TOutput* ptrOutput;\r
GLUTImageViewers viewer;\r
\r
public:\r
Viewer(bool isAnimation, bool isSelection, int pxFrame, int pyFrame):\r
- ptrProvider(TProvider::createGL()),\r
- viewer(ptrProvider, isAnimation, isSelection, pxFrame, pyFrame)\r
+ ptrOutput(TProvider::createGL()),\r
+ viewer(ptrOutput, isAnimation, isSelection, pxFrame, pyFrame)\r
+ {\r
+ }\r
+\r
+ Viewer(TOutput* output, bool isAnimation, bool isSelection, int pxFrame, int pyFrame):\r
+ ptrOutput(output),\r
+ viewer(ptrOutput, isAnimation, isSelection, pxFrame, pyFrame)\r
{\r
}\r
\r
~Viewer()\r
{\r
- delete this->ptrProvider;\r
+ delete this->ptrOutput;\r
}\r
};\r
\r
{\r
// Viewer<Rippling0Image, Rippling0Provider> rippling0(true, true, 10, 10);\r
// Viewer<Image, RipplingProvider> rippling0(true, true, 10, 10);\r
- Viewer<ImageFonctionel, MandelbrotProvider> fractalMandelbrot(true, true, 20, 20);\r
+ Viewer<ImageFonctionel, MandelbrotProvider> fractalMandelbrot(MandelbrotProvider::createGL(true), true, true, 20, 20);\r
// Viewer<ImageFonctionel, JuliaProvider> fractalJulia(true, true, 30, 30);\r
// Viewer<ImageFonctionel, NewtonProvider> newtown(true, true, 20, 20);\r
// Viewer<Image, HeatTransfertProvider> heatTransfert(true, false, 20, 20);\r
// Viewer<ImageFonctionel, RayTracingProvider> rayTracing(true, true, 20, 20);\r
\r
- GLUTImageViewers::runALL(); // Bloquant, Tant qu'une fenetre est ouverte\r
+ GLUTImageViewers::runALL(); // Bloquant, Tant qu'une fenetre est ouverte.\r
\r
return EXIT_SUCCESS;\r
}\r