Skip to content

Instantly share code, notes, and snippets.

@Eastkap
Created May 9, 2019 17:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Eastkap/72fba63275d435ad87d472526b1cb20b to your computer and use it in GitHub Desktop.
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
/* 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