1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
   |  
 
/* parallel computation of pi with monte carlo method */ 
#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/mman.h> 
#include <sys/wait.h> 
#include <sys/time.h> 
#include <sys/ipc.h>
#include <sys/shm.h>
 
 
int rdtsc()
{
    __asm__ __volatile__("rdtsc");
}
 
 
 
double* Parallel( double* smem, pid_t* pid, int nbt, long int niter, int statut, int options, int nb_current )
{
  double x,y,z;
  long int i;
  int j;
 
  srand(rdtsc());     
 
 
 
     if (nbt==1)  
               { smem[nb_current]=0;
                 for (i=0; i<(niter/nbt); i++) 
                      { x = (double) rand() / RAND_MAX; 
                        y = (double) rand() / RAND_MAX; 
                        z = x*x + y*y;
                        if (z <= 1.0) 
                 {smem[nb_current]++;}}		
               return smem;		 
		 }
 else if (nb_current==nbt) return smem;
     else {  pid[nb_current]=fork();
             if (pid[nb_current]<0) {exit(4);}
                else if (pid[nb_current]==0)
                {    smem=Parallel(smem,pid,nbt,niter,statut,options,nb_current+2);       		                            
		      // child process 
		      // compute the niter/nbt part of niter hits 
                      smem[nb_current] = 0;			      
                      for (i=0; i<(niter/nbt); i++) 
                      { x = (double) rand() / RAND_MAX;
                        y = (double) rand() / RAND_MAX; 
	                z = x*x + y*y; 
	                if (z <= 1.0) {smem[nb_current]++; }
			}
                      printf("------smem in child-----nb_current=%d ---\n",nb_current);			
		      for(j=0;j<nbt;j++)
		      {printf("smem[%d]=%f\n",j,smem[j]);}		
                      exit(0);
                }
		else
		 {    // parent process 
		      // compute the niter/nbt part of niter hits 
                      smem[nb_current+1] = 0;		       			      
                      for (i=0; i<(niter/nbt); i++) 
                      { x = (double) rand() / RAND_MAX;
                        y = (double) rand() / RAND_MAX; 
	                z = x*x + y*y; 
	                if (z <= 1.0) {smem[nb_current+1]++; }
			}
		      waitpid(pid[nb_current],&statut,options);			                      
                      printf("------smem in parent-----nb_current+1=%d ---\n",nb_current+1);			
		      for(j=0;j<nbt;j++)
		      {printf("smem[%d]=%f\n",j,smem[j]);}			
 
 
		      return smem;
 
                 }
 
}
 
}  
 
 
 int main (int argc, char** argv) 
 
 { long int niter; // total number of hits 
   long int fd;long int i;
 
   int shm_id;
   int nb_process; // number of threads 
   int nb_current=0; // current index in Parallel recursive function
   double x,y,z;
   double pi=0;
//   struct sharedMem* smem;
 
   double* smem;
   struct timeval chrono1, chrono2; 
   int micro, second; pid_t *pid; 
   int pseudo_pid;
   int statut;
   int options = 0;   
 
 
  // parse the argument 
  if (argc != 3)
   { printf ("Please, specify number of threads and iterations \n"); 
     exit (1); } 
 
     nb_process = atoi(argv[1]);        
     niter = atol(argv[2]);   
 
 
  // create the shared memory 
 fd = open ("/tmp/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
   if (fd == -1) exit(2);
 
    if (ftruncate (fd, nb_process*sizeof (double)) == -1) exit(3); 
 
    smem = mmap (NULL, nb_process*sizeof (double),
              PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (smem == MAP_FAILED) exit(1); 
 
 
     // initialize pid 
 
     pid=(pid_t*)malloc(nb_process*sizeof(pid_t));
 
     // initialize time process
 
     gettimeofday(&chrono1, NULL);
 
     // monte carlo's method in parallel 
 
     smem=Parallel(smem,pid,nb_process,niter,statut,options,nb_current);
 
 
	gettimeofday(&chrono2, NULL); 
 
	close(fd); 
	// compute ellapsed time 
	micro = chrono2.tv_usec - chrono1.tv_usec; 
	if (micro < 0) 
	{ micro += 1000000; 
	second = chrono2.tv_sec - chrono1.tv_sec - 1; } 
	else 
	second = chrono2.tv_sec - chrono1.tv_sec;
	//printf("-------------------------\n");	
	for(i=0;i<nb_process;i++) 
	{//printf("smem[%d]=%f\n",i,smem[i]);
	 pi = pi+ smem[i];}
	 pi= pi/niter;
	 pi *= 4; 
 
	// Output
 
	printf("# of trials= %ld , estimate of pi is %1.8f \n",niter,pi);
	printf("%d second %d micro ellapsed\n", second, micro);
 
  /* Don't forget to free the mmapped memory
     */
    if (munmap(smem, nb_process*sizeof (double)) == -1) {
	printf("Error un-mmapping the file\n");
	/* Decide here whether to close(fd) and exit() or not. Depends... */
    }
 
    /* Un-mmaping doesn't close the file, so we still need to do that.
     */
    close(fd);
 
 
  return 0;
 
   } | 
Partager