Created
May 9, 2019 17:36
-
-
Save Eastkap/72fba63275d435ad87d472526b1cb20b to your computer and use it in GitHub Desktop.
code that segfaults on process 3 when doing 2 process on two separate nodes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* basé sur on smallpt, a Path Tracer by Kevin Beason, 2008 | |
* http://www.kevinbeason.com/smallpt/ | |
* | |
* Converti en C et modifié par Charles Bouillaguet, 2019 | |
* | |
* Pour des détails sur le processus de rendu, lire : | |
* https://docs.google.com/open?id=0B8g97JkuSSBwUENiWTJXeGtTOHFmSm51UC01YWtCZw | |
*/ | |
#define _XOPEN_SOURCE | |
#include <math.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdbool.h> | |
#include <sys/time.h> | |
#include <sys/stat.h> /* pour mkdir */ | |
#include <unistd.h> /* pour getuid */ | |
#include <sys/types.h> /* pour getpwuid */ | |
#include <pwd.h> /* pour getpwuid */ | |
#include <mpi.h> // mpi on adore | |
#include <time.h> | |
#include <omp.h> | |
#define DEMANDE_AIDE 1 | |
#define ENVOI_AIDE 2 | |
#define AIDEFINIE 3 | |
#define TASKFINIE 9 | |
#define FINI 4 | |
#define SEUIL 4 | |
enum Refl_t {DIFF, SPEC, REFR}; /* types de matériaux (DIFFuse, SPECular, REFRactive) */ | |
struct Sphere { | |
double radius; | |
double position[3]; | |
double emission[3]; /* couleur émise (=source de lumière) */ | |
double color[3]; /* couleur de l'objet RGB (diffusion, refraction, ...) */ | |
enum Refl_t refl; /* type de reflection */ | |
double max_reflexivity; | |
}; | |
static const int KILL_DEPTH = 7; | |
static const int SPLIT_DEPTH = 4; | |
/* la scène est composée uniquement de spheres */ | |
struct Sphere spheres[] = { | |
// radius position, emission, color, material | |
{1e5, { 1e5+1, 40.8, 81.6}, {}, {.75, .25, .25}, DIFF, -1}, // Left | |
{1e5, {-1e5+99, 40.8, 81.6}, {}, {.25, .25, .75}, DIFF, -1}, // Right | |
{1e5, {50, 40.8, 1e5}, {}, {.75, .75, .75}, DIFF, -1}, // Back | |
{1e5, {50, 40.8, -1e5 + 170}, {}, {}, DIFF, -1}, // Front | |
{1e5, {50, 1e5, 81.6}, {}, {0.75, .75, .75}, DIFF, -1}, // Bottom | |
{1e5, {50, -1e5 + 81.6, 81.6}, {}, {0.75, .75, .75}, DIFF, -1}, // Top | |
{16.5, {40, 16.5, 47}, {}, {.999, .999, .999}, SPEC, -1}, // Mirror | |
{16.5, {73, 46.5, 88}, {}, {.999, .999, .999}, REFR, -1}, // Glass | |
{10, {15, 45, 112}, {}, {.999, .999, .999}, DIFF, -1}, // white ball | |
{15, {16, 16, 130}, {}, {.999, .999, 0}, REFR, -1}, // big yellow glass | |
{7.5, {40, 8, 120}, {}, {.999, .999, 0 }, REFR, -1}, // small yellow glass middle | |
{8.5, {60, 9, 110}, {}, {.999, .999, 0 }, REFR, -1}, // small yellow glass right | |
{10, {80, 12, 92}, {}, {0, .999, 0}, DIFF, -1}, // green ball | |
{600, {50, 681.33, 81.6}, {12, 12, 12}, {}, DIFF, -1}, // Light | |
{5, {50, 75, 81.6}, {}, {0, .682, .999}, DIFF, -1}, // occlusion, mirror | |
}; | |
/********** micro BLAS LEVEL-1 + quelques fonctions non-standard **************/ | |
static inline void copy(const double *x, double *y) | |
{ | |
for (int i = 0; i < 3; i++) | |
y[i] = x[i]; | |
} | |
static inline void zero(double *x) | |
{ | |
for (int i = 0; i < 3; i++) | |
x[i] = 0; | |
} | |
static inline void axpy(double alpha, const double *x, double *y) | |
{ | |
for (int i = 0; i < 3; i++) | |
y[i] += alpha * x[i]; | |
} | |
static inline void scal(double alpha, double *x) | |
{ | |
for (int i = 0; i < 3; i++) | |
x[i] *= alpha; | |
} | |
static inline double dot(const double *a, const double *b) | |
{ | |
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
} | |
static inline double nrm2(const double *a) | |
{ | |
return sqrt(dot(a, a)); | |
} | |
/********* fonction non-standard *************/ | |
static inline void mul(const double *x, const double *y, double *z) | |
{ | |
for (int i = 0; i < 3; i++) | |
z[i] = x[i] * y[i]; | |
} | |
static inline void normalize(double *x) | |
{ | |
scal(1 / nrm2(x), x); | |
} | |
/* produit vectoriel */ | |
static inline void cross(const double *a, const double *b, double *c) | |
{ | |
c[0] = a[1] * b[2] - a[2] * b[1]; | |
c[1] = a[2] * b[0] - a[0] * b[2]; | |
c[2] = a[0] * b[1] - a[1] * b[0]; | |
} | |
/****** tronque *************/ | |
static inline void clamp(double *x) | |
{ | |
for (int i = 0; i < 3; i++) { | |
if (x[i] < 0) | |
x[i] = 0; | |
if (x[i] > 1) | |
x[i] = 1; | |
} | |
} | |
double my_rand(unsigned int *a){ | |
return (double) rand_r(a)/RAND_MAX; | |
} | |
/******************************* calcul des intersections rayon / sphere *************************************/ | |
// returns distance, 0 if nohit | |
double sphere_intersect(const struct Sphere *s, const double *ray_origin, const double *ray_direction) | |
{ | |
double op[3]; | |
// Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 | |
copy(s->position, op); | |
axpy(-1, ray_origin, op); | |
double eps = 1e-4; | |
double b = dot(op, ray_direction); | |
double discriminant = b * b - dot(op, op) + s->radius * s->radius; | |
if (discriminant < 0) | |
return 0; /* pas d'intersection */ | |
else | |
discriminant = sqrt(discriminant); | |
/* détermine la plus petite solution positive (i.e. point d'intersection le plus proche, mais devant nous) */ | |
double t = b - discriminant; | |
if (t > eps) { | |
return t; | |
} else { | |
t = b + discriminant; | |
if (t > eps) | |
return t; | |
else | |
return 0; /* cas bizarre, racine double, etc. */ | |
} | |
} | |
/* détermine si le rayon intersecte l'une des spere; si oui renvoie true et fixe t, id */ | |
bool intersect(const double *ray_origin, const double *ray_direction, double *t, int *id) | |
{ | |
int n = sizeof(spheres) / sizeof(struct Sphere); | |
double inf = 1e20; | |
*t = inf; | |
for (int i = 0; i < n; i++) { | |
double d = sphere_intersect(&spheres[i], ray_origin, ray_direction); | |
if ((d > 0) && (d < *t)) { | |
*t = d; | |
*id = i; | |
} | |
} | |
return *t < inf; | |
} | |
void copy_buff(double *source,double *dest, int compte){ | |
for(int i =0;i<compte ; i++){ | |
dest[i] = source[i]; | |
} | |
} | |
/* calcule (dans out) la lumiance reçue par la camera sur le rayon donné */ | |
void radiance(const double *ray_origin, const double *ray_direction, int depth, unsigned int *prng, double *out) | |
{ | |
int id = 0; // id de la sphère intersectée par le rayon | |
double t; // distance à l'intersection | |
if (!intersect(ray_origin, ray_direction, &t, &id)) { | |
zero(out); // if miss, return black | |
return; | |
} | |
const struct Sphere *obj = &spheres[id]; | |
/* point d'intersection du rayon et de la sphère */ | |
double x[3]; | |
copy(ray_origin, x); | |
axpy(t, ray_direction, x); | |
/* vecteur normal à la sphere, au point d'intersection */ | |
double n[3]; | |
copy(x, n); | |
axpy(-1, obj->position, n); | |
normalize(n); | |
/* vecteur normal, orienté dans le sens opposé au rayon | |
(vers l'extérieur si le rayon entre, vers l'intérieur s'il sort) */ | |
double nl[3]; | |
copy(n, nl); | |
if (dot(n, ray_direction) > 0) | |
scal(-1, nl); | |
/* couleur de la sphere */ | |
double f[3]; | |
copy(obj->color, f); | |
double p = obj->max_reflexivity; | |
/* processus aléatoire : au-delà d'une certaine profondeur, | |
décide aléatoirement d'arrêter la récusion. Plus l'objet est | |
clair, plus le processus a de chance de continuer. */ | |
depth++; | |
if (depth > KILL_DEPTH) { | |
//if (erand48(PRNG_state) < p) { | |
if (my_rand(prng) < p) { | |
scal(1 / p, f); | |
} else { | |
copy(obj->emission, out); | |
return; | |
} | |
} | |
/* Cas de la réflection DIFFuse (= non-brillante). | |
On récupère la luminance en provenance de l'ensemble de l'univers. | |
Pour cela : (processus de monte-carlo) on choisit une direction | |
aléatoire dans un certain cone, et on récupère la luminance en | |
provenance de cette direction. */ | |
if (obj->refl == DIFF) { | |
//double r1 = 2 * M_PI * erand48(PRNG_state); | |
double r1 = 2 * M_PI * my_rand(prng); /* angle aléatoire */ | |
//double r2 = erand48(PRNG_state); | |
double r2 = my_rand(prng); /* distance au centre aléatoire */ | |
double r2s = sqrt(r2); | |
double w[3]; /* vecteur normal */ | |
copy(nl, w); | |
double u[3]; /* u est orthogonal à w */ | |
double uw[3] = {0, 0, 0}; | |
if (fabs(w[0]) > .1) | |
uw[1] = 1; | |
else | |
uw[0] = 1; | |
cross(uw, w, u); | |
normalize(u); | |
double v[3]; /* v est orthogonal à u et w */ | |
cross(w, u, v); | |
double d[3]; /* d est le vecteur incident aléatoire, selon la bonne distribution */ | |
zero(d); | |
axpy(cos(r1) * r2s, u, d); | |
axpy(sin(r1) * r2s, v, d); | |
axpy(sqrt(1 - r2), w, d); | |
normalize(d); | |
/* calcule récursivement la luminance du rayon incident */ | |
double rec[3]; | |
radiance(x, d, depth, prng, rec); | |
/* pondère par la couleur de la sphère, prend en compte l'emissivité */ | |
mul(f, rec, out); | |
axpy(1, obj->emission, out); | |
return; | |
} | |
/* dans les deux autres cas (réflection parfaite / refraction), on considère le rayon | |
réfléchi par la spère */ | |
double reflected_dir[3]; | |
copy(ray_direction, reflected_dir); | |
axpy(-2 * dot(n, ray_direction), n, reflected_dir); | |
/* cas de la reflection SPEculaire parfaire (==mirroir) */ | |
if (obj->refl == SPEC) { | |
double rec[3]; | |
/* calcule récursivement la luminance du rayon réflechi */ | |
radiance(x, reflected_dir, depth, prng, rec); | |
/* pondère par la couleur de la sphère, prend en compte l'emissivité */ | |
mul(f, rec, out); | |
axpy(1, obj->emission, out); | |
return; | |
} | |
/* cas des surfaces diélectriques (==verre). Combinaison de réflection et de réfraction. */ | |
bool into = dot(n, nl) > 0; /* vient-il de l'extérieur ? */ | |
double nc = 1; /* indice de réfraction de l'air */ | |
double nt = 1.5; /* indice de réfraction du verre */ | |
double nnt = into ? (nc / nt) : (nt / nc); | |
double ddn = dot(ray_direction, nl); | |
/* si le rayon essaye de sortir de l'objet en verre avec un angle incident trop faible, | |
il rebondit entièrement */ | |
double cos2t = 1 - nnt * nnt * (1 - ddn * ddn); | |
if (cos2t < 0) { | |
double rec[3]; | |
/* calcule seulement le rayon réfléchi */ | |
radiance(x, reflected_dir, depth, prng, rec); | |
mul(f, rec, out); | |
axpy(1, obj->emission, out); | |
return; | |
} | |
/* calcule la direction du rayon réfracté */ | |
double tdir[3]; | |
zero(tdir); | |
axpy(nnt, ray_direction, tdir); | |
axpy(-(into ? 1 : -1) * (ddn * nnt + sqrt(cos2t)), n, tdir); | |
/* calcul de la réflectance (==fraction de la lumière réfléchie) */ | |
double a = nt - nc; | |
double b = nt + nc; | |
double R0 = a * a / (b * b); | |
double c = 1 - (into ? -ddn : dot(tdir, n)); | |
double Re = R0 + (1 - R0) * c * c * c * c * c; /* réflectance */ | |
double Tr = 1 - Re; /* transmittance */ | |
/* au-dela d'une certaine profondeur, on choisit aléatoirement si | |
on calcule le rayon réfléchi ou bien le rayon réfracté. En dessous du | |
seuil, on calcule les deux. */ | |
double rec[3]; | |
if (depth > SPLIT_DEPTH) { | |
double P = .25 + .5 * Re; /* probabilité de réflection */ | |
//if (erand48(PRNG_state) < P) { | |
if (my_rand(prng) < P) { | |
radiance(x, reflected_dir, depth, prng, rec); | |
double RP = Re / P; | |
scal(RP, rec); | |
} else { | |
radiance(x, tdir, depth, prng, rec); | |
double TP = Tr / (1 - P); | |
scal(TP, rec); | |
} | |
} else { | |
double rec_re[3], rec_tr[3]; | |
radiance(x, reflected_dir, depth, prng, rec_re); | |
radiance(x, tdir, depth, prng, rec_tr); | |
zero(rec); | |
axpy(Re, rec_re, rec); | |
axpy(Tr, rec_tr, rec); | |
} | |
/* pondère, prend en compte la luminance */ | |
mul(f, rec, out); | |
axpy(1, obj->emission, out); | |
return; | |
} | |
double wtime() | |
{ | |
struct timeval ts; | |
gettimeofday(&ts, NULL); | |
return (double)ts.tv_sec + ts.tv_usec / 1E6; | |
} | |
int toInt(double x) | |
{ | |
return pow(x, 1 / 2.2) * 255 + .5; /* gamma correction = 2.2 */ | |
} | |
int allReceived(MPI_Request *tab,int nbproc){ | |
// return 0 si une requete nest pas finie | |
//sleep(1); | |
//printf("debut allreceived\n"); | |
int temp = 1; | |
int i; | |
for(i = 1;i<nbproc;i++){ | |
temp = 0; | |
MPI_Test(&(tab[i]),&temp,MPI_STATUS_IGNORE); | |
if(!temp){ | |
//printf("%d na pas ete recu \n",i); | |
//printf("fin 0 allreceived\n"); | |
return 0; | |
} | |
} | |
//printf("fin 1 allreceived\n"); | |
return 1; | |
} | |
void generate_image(int nblignes,int nbproc,int my_rank,int samples,double * camera_direction,double * camera_position, int h,int w, double* cx,double*cy, double* buffer,int start){ | |
//if start == 0 -> calcul classique | |
int helped = 0; // si on se fait aider ou pas | |
int infos[2] = {0,0}; //bornes des proc aidant : debut , fin | |
int i_calcul; | |
MPI_Request demande; | |
MPI_Request recoit; | |
int recu=0; | |
int i; | |
unsigned short j; | |
unsigned short PRNG_state[3] = {0, 0, 0}; | |
unsigned int prng; | |
int flag = 0; | |
//se met a ecouter si demande daide | |
MPI_Irecv( &helped, 1, MPI_INT, (my_rank+1)%nbproc, DEMANDE_AIDE ,MPI_COMM_WORLD,&demande); | |
#pragma omp parallel for private(j,i_calcul,prng,PRNG_state) | |
for (i = 0; i < nblignes; i++) { // iteration sur h | |
// ça donne le mauvais ordre i_calcul = nblignes * my_rank + i ; | |
if(start==0){ | |
i_calcul = nblignes * (nbproc - my_rank -1) + i ; | |
} | |
else{ | |
i_calcul = start + i; | |
} | |
i_calcul = nblignes * (nbproc - my_rank -1) + i ; | |
printf("le proc %d fait la ligne %d\n",my_rank,i_calcul); | |
PRNG_state[0] = 0; | |
PRNG_state[1] = 0; | |
PRNG_state[2] = i_calcul*i_calcul*i_calcul; | |
prng = (unsigned int) PRNG_state[2]; | |
for (j = 0; j < w; j++) { //iteration sur w | |
/* calcule la luminance d'un pixel, avec sur-échantillonnage 2x2 */ | |
double pixel_radiance[3] = {0, 0, 0}; | |
for (int sub_i = 0; sub_i < 2; sub_i++) { | |
for (int sub_j = 0; sub_j < 2; sub_j++) { | |
double subpixel_radiance[3] = {0, 0, 0}; | |
/* simulation de monte-carlo : on effectue plein de lancers de rayons et on moyenne */ | |
for (int s = 0; s < samples; s++) { | |
/* tire un rayon aléatoire dans une zone de la caméra qui correspond à peu près au pixel à calculer */ | |
//double r1 = 2 * erand48(PRNG_state); | |
double r1 = 2 * my_rand(&prng); | |
double dx = (r1 < 1) ? sqrt(r1) - 1 : 1 - sqrt(2 - r1); | |
double r2 = 2 * my_rand(&prng); | |
double dy = (r2 < 1) ? sqrt(r2) - 1 : 1 - sqrt(2 - r2); | |
double ray_direction[3]; | |
copy(camera_direction, ray_direction); | |
axpy(((sub_i + .5 + dy) / 2 + i_calcul) / h - .5, cy, ray_direction); | |
axpy(((sub_j + .5 + dx) / 2 + j) / w - .5, cx, ray_direction); | |
normalize(ray_direction); | |
double ray_origin[3]; | |
copy(camera_position, ray_origin); | |
axpy(140, ray_direction, ray_origin); | |
/* estime la lumiance qui arrive sur la caméra par ce rayon */ | |
double sample_radiance[3]; | |
radiance(ray_origin, ray_direction, 0, &prng, sample_radiance); | |
/* fait la moyenne sur tous les rayons */ | |
axpy(1. / samples, sample_radiance, subpixel_radiance); | |
} | |
clamp(subpixel_radiance); | |
/* fait la moyenne sur les 4 sous-pixels */ | |
axpy(0.25, subpixel_radiance, pixel_radiance); | |
} | |
} | |
/*if(start==0){ | |
copy(pixel_radiance, buffer + 3 * ((nblignes - 1 - i) * w + j)); // <-- retournement vertical | |
} | |
else{ | |
copy(pixel_radiance, buffer + 3 * ((i) * w + j)); | |
}*/ | |
copy(pixel_radiance, buffer + 3 * ((nblignes - 1 - i) * w + j)); // <-- retournement vertical | |
} | |
//printf("%d fin du calcul j\n",my_rank); | |
//printf("%d avant test\n",my_rank); | |
MPI_Test(&demande,&recu,MPI_STATUS_IGNORE); | |
//printf("%d apres test\n",my_rank); | |
if(recu){ | |
//printf("%d a recu une offre daide %d \n",my_rank,helped); | |
if(helped){ | |
//printf("%d se fait aider, il verifie\n",my_rank); | |
recu = 0; | |
MPI_Test(&recoit,&recu,MPI_STATUS_IGNORE); | |
if(recu){ | |
//printf("%d a recu les infos, il peut re ecouter\n",my_rank); | |
MPI_Irecv( &helped, 1, MPI_INT, (my_rank+1)%nbproc, DEMANDE_AIDE ,MPI_COMM_WORLD,&demande); | |
recu = 0; | |
helped = 0; | |
} | |
else{ | |
//printf("%d na tjrs pas recu\n",my_rank); | |
recu = 1; | |
} | |
} | |
else if((nblignes-i > SEUIL)){ | |
helped = (nblignes-i)/2; | |
/*infos[0] = i +1; // car on a deja calcule la ligne i | |
infos[1] = i + (nblignes-i)/2;*/ | |
infos[0] = i_calcul +1; // car on a deja calcule la ligne i | |
infos[1] = i_calcul + helped; | |
//on avance i | |
//printf("[%d]i passe de %d",my_rank,i); | |
i = i + helped - 1; //on fait i++ du coup on veut calculer | |
//printf("[%d]a %d \n",my_rank,i); | |
MPI_Send(infos,2,MPI_INT,(my_rank+1)%nbproc,ENVOI_AIDE,MPI_COMM_WORLD); //envoi de la demande | |
//printf("%d a envoye %d %d\n",my_rank,infos[0],infos[1]); | |
MPI_Irecv(buffer+(nblignes-i-1)*w*3,(infos[1]-infos[0])*w*3,MPI_DOUBLE,(my_rank+1)%nbproc,AIDEFINIE,MPI_COMM_WORLD,&recoit); | |
//printf("%d pret a recevoir %d \n",my_rank,(infos[1]-infos[0])*w*3); | |
//helped | |
helped = 1; | |
}/* | |
else{ | |
printf("%d na pas envie denvoyer car il ne lui reste que %d lignes\n",my_rank,nblignes-i); | |
//arepondu = 0; | |
}*/ | |
} | |
} | |
if(helped){ | |
flag = 0; | |
while(!flag){ | |
//bloquons jusqua reception | |
//printf("%d bloque jusqua reception avant\n",my_rank); | |
MPI_Test(&recoit, &flag, MPI_STATUS_IGNORE); | |
//printf("%d bloque jusqua reception apres\n",my_rank); | |
//usleep(5000); | |
} | |
} | |
if(!recu){ | |
//on cancel lecoute qui traine | |
//printf("%d necoute plus pour se faire aider\n",my_rank); | |
flag = 0; | |
MPI_Test(&demande,&flag,MPI_STATUS_IGNORE); | |
if(flag==-112313){ | |
//printf("%d annule la demande\n",my_rank); | |
printf("on essaye de cancel\n"); | |
MPI_Cancel(&demande); | |
printf("on reussit a cancel\n"); | |
}else{ | |
infos[0] = -1; | |
infos[1] = -1; // try not to send any garbage | |
MPI_Send(infos,2,MPI_INT,(my_rank+1)%nbproc,ENVOI_AIDE,MPI_COMM_WORLD); | |
//printf("%d repond quild navait pas envie de se fire aider\n",my_rank); | |
} | |
} | |
/*else if(!arepondu){ | |
infos[0] = -1; | |
infos[1] = -1; // try not to send any garbage | |
MPI_Send(infos,2,MPI_INT,(my_rank+1)%nbproc,ENVOI_AIDE,MPI_COMM_WORLD); | |
// on repond a la fin quon navait pas envie de lui repondre | |
}*/ | |
//printf("%d bye\n",my_rank); | |
} | |
int main(int argc, char **argv) | |
{ | |
/* Petit cas test (small, quick and dirty): | |
int w = 320; | |
int h = 200; | |
int samples = 200;*/ | |
// tout petit cas test (ver small, very quick and very dirty): | |
int w = 320; | |
int h = 200; | |
int samples = 25; | |
int i; | |
/* Gros cas test (big, slow and pretty): */ | |
/* int w = 3840; */ | |
/* int h = 2160; */ | |
/* int samples = 5000; */ | |
if (argc == 2) | |
samples = atoi(argv[1]) / 4; | |
int my_rank, nbproc; | |
MPI_Init(&argc, &argv); | |
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); | |
MPI_Comm_size(MPI_COMM_WORLD, &nbproc); | |
MPI_Request temp; | |
static const double CST = 0.5135; /* ceci défini l'angle de vue */ | |
double camera_position[3] = {50, 52, 295.6}; | |
double camera_direction[3] = {0, -0.042612, -1}; | |
normalize(camera_direction); | |
/* incréments pour passer d'un pixel à l'autre */ | |
double cx[3] = {w * CST / h, 0, 0}; | |
double cy[3]; | |
cross(cx, camera_direction, cy); /* cy est orthogonal à cx ET à la direction dans laquelle regarde la caméra */ | |
normalize(cy); | |
scal(CST, cy); | |
/* précalcule la norme infinie des couleurs */ | |
int n = sizeof(spheres) / sizeof(struct Sphere); | |
for (i = 0; i < n; i++) { | |
double *f = spheres[i].color; | |
if ((f[0] > f[1]) && (f[0] > f[2])) | |
spheres[i].max_reflexivity = f[0]; | |
else { | |
if (f[1] > f[2]) | |
spheres[i].max_reflexivity = f[1]; | |
else | |
spheres[i].max_reflexivity = f[2]; | |
} | |
} | |
//int* pfinis = NULL; | |
double *image = NULL; | |
if(my_rank==0){ //on alloue limage finale que dans le processus principal | |
image = malloc(3 * w * h * sizeof(*image)); | |
if (image == NULL) { | |
perror("Impossible d'allouer l'image"); | |
exit(1); | |
} | |
//pfinis = malloc(nbproc * sizeof(*pfinis) ); | |
} | |
double *buffer = NULL; | |
int nblignes = h / nbproc; // nombre de lignes que chaque proc calcule | |
//printf("%d sont calculees par chaque %d proc\n",nblignes,nbproc); //on affiche | |
//allocation du buffer | |
MPI_Request *reception = NULL; // on note | |
buffer = malloc(3 * nblignes * w * sizeof(*image)); | |
if(buffer == NULL){ | |
perror("Impossible d'allouer l'image"); | |
exit(1); | |
} | |
if(my_rank==0){ | |
reception = (MPI_Request *) malloc((nbproc) * sizeof(MPI_Request)); | |
for(i = 0;i<nbproc;i++){ | |
//MPI_Recv( image+i*(nblignes*w*3), nblignes*w*3, MPI_DOUBLE, i, TASKFINIE,MPI_COMM_WORLD,MPI_STATUS_IGNORE); // le bug fut ici | |
MPI_Irecv(image+i*(nblignes*w*3),nblignes*w*3,MPI_DOUBLE,i,TASKFINIE,MPI_COMM_WORLD,&(reception[i]) ); | |
//printf("recoit le process %d en async\n",i); | |
} | |
} | |
double tini = wtime(); | |
/* boucle principale */ | |
generate_image(nblignes,nbproc,my_rank,samples,camera_direction,camera_position,h,w,cx,cy, buffer ,0); // 0 indique que c'est le calcul de base | |
//printf("%d a fini son calcul principal\n",my_rank); | |
//reception et envoi de la fin | |
/*if(my_rank == 0){ | |
copy_buff(buffer,image,nblignes*w*3); | |
} | |
else{ | |
MPI_Isend(buffer, nblignes*w*3, MPI_DOUBLE, 0, TASKFINIE,MPI_COMM_WORLD,&send_request); // on envoie | |
printf("%d a envoye son calcul principal\n",my_rank); | |
}*/ | |
/*MPI_Isend(buffer, nblignes*w*3, MPI_DOUBLE, 0, TASKFINIE,MPI_COMM_WORLD,&send_request); // on envoie | |
printf("%d a envoye son calcul principal\n",my_rank); | |
//securite, on ne peut free que quand | |
free(buffer);*/ | |
MPI_Send(buffer, nblignes*w*3, MPI_DOUBLE, 0, TASKFINIE,MPI_COMM_WORLD); // on envoie | |
//printf("%d a envoye son calcul principal\n",my_rank); | |
//free(buffer); | |
int indices[2] = {0,0}; | |
int over = 0; | |
int recu = 0,indicesrecus = 0,listening = 0; | |
int zeroatoutrecu = 0; | |
MPI_Request qqn,fini,rtemp; | |
MPI_Irecv(&recu,1,MPI_INT,0,FINI,MPI_COMM_WORLD,&fini); //estce la fin? | |
int ondemande = 0; // pb ici avec les communications de fin | |
int reponse = 0; | |
while(!over){ | |
if(my_rank == 0){ | |
zeroatoutrecu = allReceived(reception,nbproc); | |
//printf("0 check et trouve %d\n",zeroatoutrecu); | |
if(zeroatoutrecu){ | |
//printf("0 a tout recu\n"); | |
for(i = 0;i<nbproc;i++){ | |
//MPI_Send(&i,1,MPI_INT,i,FINI,MPI_COMM_WORLD,&temp); // on envoie la fin atout le monde en async | |
MPI_Send(&i, 1, MPI_INT, i, FINI,MPI_COMM_WORLD); | |
} | |
} | |
} | |
MPI_Test(&fini, &over, MPI_STATUS_IGNORE); // on maj | |
if(over){ | |
//printf("%d proc recoit la fin\n",my_rank); | |
break; | |
} | |
if(!ondemande){ | |
//on demande au proc n-1 | |
MPI_Isend(&ondemande, 1 , MPI_INT, (my_rank-1+nbproc)%nbproc , DEMANDE_AIDE, MPI_COMM_WORLD, &qqn); | |
ondemande = 1; | |
//printf("%d a demande a -1 si besoin daide\n",my_rank); | |
}else{ | |
MPI_Test(&qqn,&reponse,MPI_STATUS_IGNORE); | |
if(reponse){ | |
if(!listening){ | |
//printf("%d %d\n",my_rank,reponse); | |
//printf("%d va recevoir de -1 ou Laider\n",my_rank); | |
//on a recu la reponse de qqn | |
// ça bloque ici faire non bloquant et continuer a verifier si reception -> TODO | |
//TODO | |
//MPI_Recv(indices,2,MPI_INT,(my_rank-1+nbproc)%nbproc, ENVOI_AIDE,MPI_COMM_WORLD,MPI_STATUS_IGNORE); | |
MPI_Irecv(&indices,2,MPI_INT,(my_rank-1+nbproc)%nbproc,ENVOI_AIDE,MPI_COMM_WORLD,&rtemp); | |
listening = 1; | |
}else{ | |
MPI_Test(&rtemp,&indicesrecus,MPI_STATUS_IGNORE); | |
//printf("%d 693\n",my_rank); | |
if(indicesrecus){ | |
//printf("%d a recu %d %d \n",my_rank,indices[0],indices[1]); | |
if(indices[0]!=-1){ | |
//-1 est un indice impossible, c'est la facon du lautre proc de dire quil voulait pas travailler avec nous | |
nblignes = indices[1]-indices[0]; | |
//buffer = malloc(3 * nblignes * w * sizeof(*image)); | |
//buffer = malloc(3 * (nblignes+1) * w * sizeof(*image)); | |
//on calcule | |
generate_image(nblignes,nbproc,my_rank,samples,camera_direction,camera_position,h,w,cx,cy, buffer,indices[0]); | |
//on envoie | |
//MPI_Isend(buffer, nblignes*w*3, MPI_DOUBLE, (my_rank-1+nbproc)%nbproc, AIDEFINIE,MPI_COMM_WORLD,&send_request); // a verifier les tags | |
MPI_Send(buffer, nblignes*w*3, MPI_DOUBLE, (my_rank-1+nbproc)%nbproc, AIDEFINIE,MPI_COMM_WORLD); | |
//printf("%d envoie %d \n",my_rank,nblignes*w*3); | |
// on se remet pret pour un autre calcul | |
//free(buffer); | |
} | |
ondemande = 0; | |
reponse = 0; | |
listening = 0; | |
indicesrecus = 0; | |
} | |
} | |
} | |
} | |
//usleep(5000); | |
} | |
//MPI_Send(0,fini,MPI_INT,int destination, int tag,MPI_Comm communicator); | |
fprintf(stderr, "\n"); | |
//printf("processus %d fini\n",my_rank); | |
//MPI_Gather(buffer, w*nblignes*3, MPI_DOUBLE, image, w*nblignes*3, MPI_DOUBLE, 0, MPI_COMM_WORLD); | |
/* stocke l'image dans un fichier au format NetPbm */ | |
if(my_rank==0){ | |
printf("le calcul a pris %f s.\n",wtime()-tini); | |
struct passwd *pass; | |
char nom_sortie[100] = ""; | |
char nom_rep[30] = ""; | |
pass = getpwuid(getuid()); | |
//sprintf(nom_rep, "/tmp/%s", pass->pw_name); | |
sprintf(nom_rep, "./%s", pass->pw_name); | |
mkdir(nom_rep, S_IRWXU); | |
sprintf(nom_sortie, "%s/image.ppm", nom_rep); | |
FILE *f = fopen(nom_sortie, "w"); | |
fprintf(f, "P3\n%d %d\n%d\n", w, h, 255); | |
for (i = 0; i < w * h; i++) | |
fprintf(f,"%d %d %d ", toInt(image[3 * i]), toInt(image[3 * i + 1]), toInt(image[3 * i + 2])); | |
fclose(f); | |
free(image); | |
free(reception); | |
} | |
free(buffer); | |
MPI_Finalize(); | |
return 0 ; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment