私は私のクラスメートと議論することにより、自分のコードでミスを発見し、それを整流し、ここにも、コードを並列化次のコードです:
/**
To compile the program: gcc sequential.c -lm
To run the program: ./a.out
**/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#define TOTAL_NUMBER_OF_NEUTRONS 10000000 //Total number of neutrons
#define SCATTERING_COMPONENT 0.7 // Scattering component of C
#define ABSORBING_COMPONENT 0.3 // Absorbing component of C
#define THICKNESS_OF_THE_PLATE 8 //Thickness of the Plate
#define NUMBER_OF_ITERATIONS 1000
int no_of_particles_reflected=0, no_of_particles_absorbed=0, no_of_particles_transmitted=0;
double total_amount_absorbed,total_amount_reflected,total_amount_transmitted;
double distance_travelled_before_collision; // Distance travelled by neutron before colliding from the plate
double C ; // mean distance between neutron/atom interactions is 1/C
int flag= 1; int counter= 0;
struct neutron
{
double d; // Direction of the neutron (measured in radians between 0 and pi)
double x; // Position of particle in plate(0<=x<=H),H is the thickness of the plate
};
struct neutron nt;
void neutron_model()
{
double random_number_generator; // Uniform random number generator
total_amount_absorbed=0,total_amount_reflected=0,total_amount_transmitted=0;
for(int i=1;i<=TOTAL_NUMBER_OF_NEUTRONS;i++)
{
random_number_generator=rand()%TOTAL_NUMBER_OF_NEUTRONS;
random_number_generator=1/random_number_generator;
nt.d=0;
nt.x=0;
flag=1;
while(flag)
{
distance_travelled_before_collision=-(1/C)*log(random_number_generator);
nt.x=distance_travelled_before_collision*cos(nt.d);
if (nt.x<0)
{
no_of_particles_reflected++;
flag=0;
}
else if(nt.x>=THICKNESS_OF_THE_PLATE)
{
no_of_particles_transmitted++;
flag=0;
}
else
{
if(random_number_generator<(ABSORBING_COMPONENT/C))
{
no_of_particles_absorbed++;
flag=0;
}
else
{
nt.d=random_number_generator*(22.0/7.0);
counter++;
if(counter==NUMBER_OF_ITERATIONS)
{
no_of_particles_absorbed++;
flag=0;
counter=0;
}
}
}
}
}
}
int main(int argc, char *argv[])
{
C=SCATTERING_COMPONENT + ABSORBING_COMPONENT;
clock_t start, end;
double diff_t;
diff_t = 0.0;
//start the clock
start= clock();
neutron_model();
//stop the clock
end = clock();
diff_t = ((double) (end - start))/CLOCKS_PER_SEC;
total_amount_reflected=((double)no_of_particles_reflected/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_absorbed=((double)no_of_particles_absorbed/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_transmitted=((double)no_of_particles_transmitted/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
printf("\nDATA VALUE ASSUMED:-\n");
printf("***********************************************************************\n");
printf("TOTAL_NUMBER_OF_NEUTRONS: %d\n",TOTAL_NUMBER_OF_NEUTRONS);
printf("SCATTERING_COMPONENT: %f\n",SCATTERING_COMPONENT);
printf("ABSORBING_COMPONENT: %f\n",ABSORBING_COMPONENT);
printf("THICKNESS_OF_THE_PLATE: %d\n",THICKNESS_OF_THE_PLATE);
printf("***********************************************************************\n\n");
printf("Total particles reflected,absorbed and transmitted respectively are: %d, %d, %d \n",no_of_particles_reflected,no_of_particles_absorbed,no_of_particles_transmitted);
printf("Percentage of particles reflected,absorbed and transmitted respectively are: %lf, %lf, %lf\n", total_amount_reflected, total_amount_absorbed, total_amount_transmitted);
printf("Total time taken in sec %10.6lf\n",diff_t);
return 0;
}
MPIバージョン:
/**
To compile the program: mpicc -o neutron_transport with_MPI.c -lm
To run the program: mpirun -np <specify no. of processes> neutron_transport
**/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<mpi.h>
#define TOTAL_NUMBER_OF_NEUTRONS 1000 //Total number of neutrons
#define SCATTERING_COMPONENT 0.7 // Scattering component of C
#define ABSORBING_COMPONENT 0.3 // Absorbing component of C
#define THICKNESS_OF_THE_PLATE 4 //Thickness of the Plate
#define NUMBER_OF_ITERATIONS 1000
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)
#define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1,p,n)-BLOCK_LOW(id,p,n)) //Block Size for each process
struct neutron
{
long double d; // Direction of the neutron (measured in radians between 0 and pi)
long double x; // Position of particle in plate(0<=x<=H) where H is the thickness of the plate
};
int main(int argc, char *argv[])
{
int process_id; //Process Identifier
int number_of_processes; //Number of Processes in the communicator
MPI_Init(&argc,&argv); //Starting of MPI program
MPI_Comm_rank(MPI_COMM_WORLD,&process_id); //Determine the process ID number in the communicator
MPI_Comm_size(MPI_COMM_WORLD,&number_of_processes); //Determine the number of processes in the communicator
int i=0; //Loop iterator
int counter=0;
int buffer_share_for_each_process=0;
double C ; // mean distance between neutron/atom interactions is 1/C
C=SCATTERING_COMPONENT + ABSORBING_COMPONENT;
int flag= 1;
double random_number_generator; // Uniform random number
double distance_travelled_before_collision; // Distance travelled by neutron before collision
struct neutron nt;
double total_amount_absorbed,total_amount_reflected,total_amount_transmitted;
int count_of_reflected_absorbed_transmitted[3];
count_of_reflected_absorbed_transmitted[0]=0;
count_of_reflected_absorbed_transmitted[1]=0;
count_of_reflected_absorbed_transmitted[2]=0;
int global_count_of_reflected_absorbed_transmitted[3];
buffer_share_for_each_process= BLOCK_SIZE(process_id,number_of_processes,TOTAL_NUMBER_OF_NEUTRONS);
double elapsed_time1; //Timer variables
elapsed_time1= -MPI_Wtime();
if(number_of_processes > TOTAL_NUMBER_OF_NEUTRONS)
{
if(!process_id)
printf("Too many processes. Kindly provide lesser number of processes.\n");
MPI_Finalize();
exit(1);
}
for(int i=1;i<=buffer_share_for_each_process;i++)
{
random_number_generator=rand()%TOTAL_NUMBER_OF_NEUTRONS;
random_number_generator=1/random_number_generator;
nt.d=0;
nt.x=0;
flag=1;
distance_travelled_before_collision=-(1/C)*log(random_number_generator);
nt.x=distance_travelled_before_collision*cos(nt.d);
while(flag)
{
distance_travelled_before_collision=-(1/C)*log(random_number_generator);
nt.x=distance_travelled_before_collision*cos(nt.d);
if (nt.x<0)
{
count_of_reflected_absorbed_transmitted[0]++;
flag=0;
}
else if(nt.x>=THICKNESS_OF_THE_PLATE)
{
count_of_reflected_absorbed_transmitted[2]++;
flag=0;
}
else
{
if(random_number_generator<(ABSORBING_COMPONENT/C))
{
count_of_reflected_absorbed_transmitted[1]++;
flag=0;
}
else
{
nt.d=random_number_generator*(22.0/7.0);
counter++;
if(counter==NUMBER_OF_ITERATIONS)
{
count_of_reflected_absorbed_transmitted[1]++;
flag=0;
counter=0;
}
}
}
}
}
for(int i= 0 ; i < 3 ; i ++)
MPI_Reduce(&count_of_reflected_absorbed_transmitted[i], &global_count_of_reflected_absorbed_transmitted[i], 1, MPI_INT,MPI_SUM,0, MPI_COMM_WORLD) ;
elapsed_time1+= MPI_Wtime();
MPI_Barrier(MPI_COMM_WORLD);
if(!process_id)
{
total_amount_reflected=((double)global_count_of_reflected_absorbed_transmitted[0]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_absorbed=((double)global_count_of_reflected_absorbed_transmitted[1]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_transmitted=((double)global_count_of_reflected_absorbed_transmitted[2]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
printf("\nDATA VALUE ASSUMED:-\n");
printf("*****************************************************************************************\n");
printf("TOTAL_NUMBER_OF_NEUTRONS: %d\n",TOTAL_NUMBER_OF_NEUTRONS);
printf("SCATTERING_COMPONENT: %f\n",SCATTERING_COMPONENT);
printf("ABSORBING_COMPONENT: %f\n",ABSORBING_COMPONENT);
printf("THICKNESS_OF_THE_PLATE: %d\n",THICKNESS_OF_THE_PLATE);
printf("TOTAL NUMBER OF PROCESSES: %d\n",number_of_processes);
printf("*****************************************************************************************\n\n");
printf("Total particles reflected,absorbed and transmitted respectively are: %d, %d, %d \n",global_count_of_reflected_absorbed_transmitted[0],global_count_of_reflected_absorbed_transmitted[1],global_count_of_reflected_absorbed_transmitted[2]);
printf("Percentage of particles reflected,absorbed and transmitted respectively are: %lf, %lf, %lf\n", total_amount_reflected, total_amount_absorbed, total_amount_transmitted);
printf("Total time taken in sec %10.6f\n",elapsed_time1);
}
MPI_Finalize();
return 0;
}
OpenMPのバージョン:
/**
To compile the program: gcc -fopenmp with_open_mp.c -lm
To run the program: ./a.out
**/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<omp.h>
#define TOTAL_NUMBER_OF_NEUTRONS 10000000 //Total number of neutrons
#define SCATTERING_COMPONENT 0.7 // Scattering component of C
#define ABSORBING_COMPONENT 0.3 // Absorbing component of C
#define THICKNESS_OF_THE_PLATE 5 //Thickness of the Plate
#define NUMBER_OF_ITERATIONS 1000
#define TOTAL_NUMBER_OF_THREADS 500
struct neutron
{
double d; // Direction of the neutron (measured in radians between 0 and pi)
double x; // Position of particle in plate(0<=x<=H) where H is the thickness of the plate
};
int main(int argc, char *argv[])
{
double C ; // mean distance between neutron/atom interactions is 1/C
C=SCATTERING_COMPONENT + ABSORBING_COMPONENT;
int no_of_particles_reflected=0, no_of_particles_absorbed=0, no_of_particles_transmitted=0;
int flag= 1;
double random_number_generator; // Uniform random number
double distance_travelled_before_collision; // Distance travelled by neutron before collision
struct neutron nt;
double total_amount_absorbed,total_amount_reflected,total_amount_transmitted;
int counter= 0;
srand(time(NULL));
clock_t start, end;
double diff_t;
diff_t = 0.0;
//start the clock
start= clock();
//int t=omp_get_num_procs();
omp_set_num_threads(TOTAL_NUMBER_OF_THREADS);
#pragma omp parallel for reduction(+:no_of_particles_reflected,no_of_particles_absorbed,no_of_particles_transmitted)
for(int i=1;i<=TOTAL_NUMBER_OF_NEUTRONS;i++)
{
random_number_generator=rand()%TOTAL_NUMBER_OF_NEUTRONS;
random_number_generator=1/random_number_generator;
nt.d=0;
nt.x=0;
flag=1;
while(flag)
{
distance_travelled_before_collision=-(1/C)*log(random_number_generator);
nt.x=distance_travelled_before_collision*cos(nt.d);
if (nt.x<0)
{
no_of_particles_reflected++;
flag=0;
}
else if(nt.x>=THICKNESS_OF_THE_PLATE)
{
no_of_particles_transmitted++;
flag=0;
}
else
{
if(random_number_generator<(ABSORBING_COMPONENT/C))
{
no_of_particles_absorbed++;
flag=0;
}
else
{
nt.d=random_number_generator*(22.0/7.0);
counter++;
if(counter==NUMBER_OF_ITERATIONS)
{
no_of_particles_absorbed++;
flag=0;
counter=0;
}
}
}
}
}
//stop the clock
end = clock();
diff_t = ((double) (end - start))/CLOCKS_PER_SEC;
printf("\nDATA VALUE ASSUMED:-\n");
printf("*****************************************************************************************\n");
printf("TOTAL_NUMBER_OF_NEUTRONS: %d\n",TOTAL_NUMBER_OF_NEUTRONS);
printf("SCATTERING_COMPONENT: %f\n",SCATTERING_COMPONENT);
printf("ABSORBING_COMPONENT: %f\n",ABSORBING_COMPONENT);
printf("THICKNESS_OF_THE_PLATE: %d\n",THICKNESS_OF_THE_PLATE);
printf("TOTAL NUMBER OF THREADS: %d\n",TOTAL_NUMBER_OF_THREADS);
printf("*****************************************************************************************\n\n");
total_amount_reflected=((double)no_of_particles_reflected/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_absorbed=((double)no_of_particles_absorbed/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_transmitted=((double)no_of_particles_transmitted/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
printf("Total particles reflected,absorbed and transmitted respectively are: %d, %d, %d \n",no_of_particles_reflected,no_of_particles_absorbed,no_of_particles_transmitted);
printf("The amount reflected,absorbed and transmitted respectively are: %lf, %lf, %lf\n", total_amount_reflected, total_amount_absorbed, total_amount_transmitted);
printf("Total time taken in sec %10.6lf\n",diff_t);
return 0;
}
ハイブリッドバージョンのMPIとOpenMP:
/**
To compile the program: mpicc -fopenmp mpi_openmp.c -o hybrid -lm
To run the program: mpirun -np <specify number of processes> ./hybrid
**/
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<omp.h>
#include<mpi.h>
#define TOTAL_NUMBER_OF_NEUTRONS 10000000 //Total number of neutrons
#define SCATTERING_COMPONENT 0.7 // Scattering component of C
#define ABSORBING_COMPONENT 0.3 // Absorbing component of C
#define THICKNESS_OF_THE_PLATE 3 //Thickness of the Plate
#define BLOCK_LOW(id,p,n) ((id)*(n)/(p))
#define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)
#define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1,p,n)-BLOCK_LOW(id,p,n)) //Block Size for each process
#define NUMBER_OF_ITERATIONS 1000
#define TOTAL_NUMBER_OF_THREADS 500 //Total number of threads
struct neutron
{
double d; // Direction of the neutron (measured in radians between 0 and pi)
double x; // Position of particle in plate(0<=x<=H) where H is the thickness of the plate
};
int main(int argc, char *argv[])
{
struct neutron nt;
int process_id; //Process Identifier
int number_of_processes; //Number of Processes in the communicator
MPI_Init(&argc,&argv); //Starting of MPI program
MPI_Comm_rank(MPI_COMM_WORLD,&process_id); //Determine the process ID number in the communicator
MPI_Comm_size(MPI_COMM_WORLD,&number_of_processes); //Determine the number of processes in the communicator
double C ; // mean distance between neutron/atom interactions is 1/C
C=SCATTERING_COMPONENT + ABSORBING_COMPONENT;
int flag= 1;
double random_number_generator; // Uniform random number
double distance_travelled_before_collision; // Distance travelled by neutron before collision
int no_of_particles_reflected=0, no_of_particles_absorbed=0, no_of_particles_transmitted=0;
double total_amount_absorbed,total_amount_reflected,total_amount_transmitted;
int counter= 0;
int buffer_share_for_each_process=0;
srand(time(NULL));
int count_of_reflected_absorbed_transmitted[3];
count_of_reflected_absorbed_transmitted[0]=0;
count_of_reflected_absorbed_transmitted[1]=0;
count_of_reflected_absorbed_transmitted[2]=0;
int global_count_of_reflected_absorbed_transmitted[3];
buffer_share_for_each_process= BLOCK_SIZE(process_id,number_of_processes,TOTAL_NUMBER_OF_NEUTRONS);
double elapsed_time1; //Timer variables
elapsed_time1= -MPI_Wtime();
//int t=omp_get_num_procs();
omp_set_num_threads(TOTAL_NUMBER_OF_THREADS);
if((number_of_processes) > TOTAL_NUMBER_OF_NEUTRONS)
{
if(!process_id)
printf("Too many processes. Kindly provide lesser number of processes.\n");
MPI_Finalize();
exit(1);
}
#pragma omp parallel for
for(int i=1;i<=buffer_share_for_each_process;i++)
{
//printf("Buffer_Share= %d by process %d (thread %d out of %d)\n",buffer_share_for_each_process,process_id,omp_get_thread_num(),omp_get_num_threads());
random_number_generator=rand()%TOTAL_NUMBER_OF_NEUTRONS;
random_number_generator=1/random_number_generator;
nt.d=0;
nt.x=0;
flag=1;
while(flag)
{
distance_travelled_before_collision=-(1/C)*log(random_number_generator);
nt.x=distance_travelled_before_collision*cos(nt.d);
if (nt.x<0)
{
count_of_reflected_absorbed_transmitted[0]++;
flag=0;
}
else if(nt.x>=THICKNESS_OF_THE_PLATE)
{
count_of_reflected_absorbed_transmitted[2]++;
flag=0;
}
else
{
if(random_number_generator<(ABSORBING_COMPONENT/C))
{
count_of_reflected_absorbed_transmitted[1]++;
flag=0;
}
else
{
nt.d=random_number_generator*(22.0/7.0);
counter++;
if(counter==NUMBER_OF_ITERATIONS)
{
count_of_reflected_absorbed_transmitted[1]++;
flag=0;
counter=0;
}
}
}
}
}
for(int i= 0 ; i < 3 ; i ++)
MPI_Reduce(&count_of_reflected_absorbed_transmitted[i], &global_count_of_reflected_absorbed_transmitted[i], 1, MPI_INT,MPI_SUM,0, MPI_COMM_WORLD) ;
elapsed_time1+= MPI_Wtime();
MPI_Barrier(MPI_COMM_WORLD);
if(!process_id)
{
total_amount_reflected=((double)global_count_of_reflected_absorbed_transmitted[0]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_absorbed=((double)global_count_of_reflected_absorbed_transmitted[1]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
total_amount_transmitted=((double)global_count_of_reflected_absorbed_transmitted[2]/(double)TOTAL_NUMBER_OF_NEUTRONS)*100.0;
printf("\nDATA VALUE ASSUMED:-\n");
printf("*****************************************************************************************\n");
printf("TOTAL_NUMBER_OF_NEUTRONS: %d\n",TOTAL_NUMBER_OF_NEUTRONS);
printf("SCATTERING_COMPONENT: %f\n",SCATTERING_COMPONENT);
printf("ABSORBING_COMPONENT: %f\n",ABSORBING_COMPONENT);
printf("THICKNESS_OF_THE_PLATE: %d\n",THICKNESS_OF_THE_PLATE);
printf("TOTAL NUMBER OF PROCESSES: %d\n",number_of_processes);
printf("TOTAL NUMBER OF THREADS: %d\n",TOTAL_NUMBER_OF_THREADS);
printf("*****************************************************************************************\n\n");
printf("Total particles reflected,absorbed and transmitted respectively are: %d, %d, %d \n",global_count_of_reflected_absorbed_transmitted[0],global_count_of_reflected_absorbed_transmitted[1],global_count_of_reflected_absorbed_transmitted[2]);
printf("Percentage of particles reflected,absorbed and transmitted respectively are: %lf, %lf, %lf\n", total_amount_reflected, total_amount_absorbed, total_amount_transmitted);
printf("Total time taken in sec %10.6f\n",elapsed_time1);
}
MPI_Finalize();
return 0;
}
1)_value_は、 'double C 'の' C'とは何ですか? ... L = - (1/C)* log(u); '? 2) 'cos(nt.d)'の代わりに 'cosl(nt.d)'を使うことを提案する。 3)コンパイラの警告を有効にする - あなたの時間を節約します。 – chux
「C」を初期化することはできません。 – 4386427
トピックの:常に 'scanfによって返された値を確認してください – 4386427