MPI: Broadcasting a long long int - c

This program estimates Pi by throwing random "darts" (sampling points) to a circle or radius=1 inscribed inside a square board of length=2. Using the relationship
Area of circle / Area of Square = Pi/4
we can estimate Pi using the same relationship expressed as
Darts Inside Circle / Darts Outside Circle = Pi/4
The program works fine when I specify NDARTS in a #define, but when trying to broadcast it as a long long int, read from scanf, I get the following execution error:
mpirun -np 4 ./pi_montecarlo.x
-----------------------------------------------------------------------------
One of the processes started by mpirun has exited with a nonzero exit
code. This typically indicates that the process finished in error.
If your process did not finish in error, be sure to include a "return
0" or "exit(0)" in your C code before exiting the application.
PID 10591 failed on node n0 (127.0.0.1) due to signal 11.
Why?
Is there anything wrong with my MPI_Bcast declaration?
long long int *NDARTS=0;
scanf("%Ld",NDARTS);
MPI_Bcast(NDARTS, 1, MPI_LONG_LONG_INT, 0, MPI_COMM_WORLD);
Full code:
/*
mpicc -g -Wall -lm pi_montecarlo3.c -o pi_montecarlo.x
mpirun -np 4 ./pi_montecarlo.x
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <mpi.h>
#define MASTER 0
#define PI 3.1415926535
d ouble pseudo_random (double a, double b) {
double r;
r = ((b-a) * ((double) rand() / (double) RAND_MAX)) +a;
return r;
}
int main(int argc, char*argv[]){
long long int *NDARTS=0;
int proc_id,
n_procs,
llimit,
ulimit,
n_circle,
i;
double pi_current,
pi_sum,
x,
y,
z,
error,
start_time,
end_time;
struct timeval stime;
llimit = -1;
ulimit = 1;
n_circle =0;
MPI_Init(&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &proc_id);
MPI_Comm_size (MPI_COMM_WORLD, &n_procs);
if (proc_id == MASTER){
printf("\nMonte Carlo Method to estimate Pi \n\n");
printf("Introduce Number of Darts \n");
scanf("%Ld",NDARTS);
printf(" Number of processes: %d \n", n_procs);
printf(" Number of darts: %Ld \n", *NDARTS);
MPI_Bcast(NDARTS, 1, MPI_LONG_LONG_INT, 0, MPI_COMM_WORLD);
start_time = MPI_Wtime();
}
gettimeofday(&stime, NULL);
srand(stime.tv_usec * stime.tv_usec * stime.tv_usec * stime.tv_usec);
for (i=1; i<=*NDARTS;i++){
x = pseudo_random(llimit, ulimit);
y = pseudo_random(llimit, ulimit);
z = pow(x,2) + pow(y,2);
if (z<=1.0){
n_circle++;
}
}
pi_current = 4.0 * (double)n_circle / (double) *NDARTS;
MPI_Reduce (&pi_current, &pi_sum, 1, MPI_DOUBLE, MPI_SUM, MASTER, MPI_COMM_WORLD);
if (proc_id == MASTER) {
pi_sum = pi_sum / n_procs;
error = fabs ((pi_sum -PI) / PI) *100;
end_time = MPI_Wtime();
printf("Known value of PI : %11.10f \n", PI);
printf("Estimated Value of PI : %11.10f\n", pi_sum);
printf("Error Percentage : %10.8f\n", error);
printf("Time : %10.8f\n\n", end_time - start_time);
}
MPI_Finalize();
return 0;
}

You're not using scanf() correctly. It should be like this instead:
long long int NDARTS;
scanf("%lld",&NDARTS);
MPI_Bcast(&NDARTS, 1, MPI_LONG_LONG_INT, 0, MPI_COMM_WORLD);
In your current code, long long int *NDARTS=0; effectively initializes NDARTS as a NULL pointer. So scanf() will obviously seg-fault when it tries to write to it.

Related

How do i make c threads do cyclyc sum?

So i have this program im working on, and the guist of it is that i need to do some operations with threads, following the next shcheme: The j-th thread Hj calculates a group of 100 consecutive iterations of the sum, making a cyclic distribution of the groups among all the threads. For example, if H = 4, the
thread H2 does the calculation of iterations [100..199, 500..599, 900..999, ...].
To ensure no data races occur, the threads must work each on a different sum variable.
Then compare after joining the threads the result achieved by the threads and the one done sequentally.
Here is the code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#include <sys/time.h>
#define H 4
double res[H] = {0};
//Time function
float restar_tiempo(struct timeval *inicio, struct timeval *fin) {
return (fin->tv_sec - inicio->tv_sec) + 1e-6 * (fin->tv_usec - inicio->tv_usec);
}
//Thread function
void *_hilo(void *arg) {
int a = * ((int*)arg);
double pi = 0;
double n = 100 * a;
while (n < 10000000) {
res[a] += (pow(-1, n) / pow(4, n)) * ((2 / (4 * n + 1)) + (2 / (4 * n + 2)) + (1 / (4 * n + 3)));
pi++;
n++;
if ((int) n % 100 == 0)
n += (H - 1)*100;
}
printf("Result on thread[%d]: %f\n", a, res[a]);
pthread_exit(NULL);
}
int main() {
pthread_t hilo[H];
struct timeval in, mid, fin;
gettimeofday(&in, NULL);
for (int i = 0; i < H; i++) {
int* p = malloc(sizeof (int));
*p = i;
printf("Esto es i: %d\n", i);
res[i] = 0;
if (pthread_create(&hilo[i], NULL, _hilo, p) != 0) {
perror(" Error creando hilo");
exit(EXIT_FAILURE);
}
free(p);
}
//Join
for (int i = 0; i < H; i++)
pthread_join(hilo[i], NULL);
//Partial sum
double f = 0;
for (int i = 0; i < H; i++){
printf("Resultado parcial de hilo %d: %f\n", i, res[i]);
f += res[i];
}
//Total partial sum
printf("Resultado total: %lf\n", f);
//printf("Hola/n");
gettimeofday(&mid, NULL);
//Secuential sum
double s = 0;
for (double n = 0; n < 10000000; n++)
s += (pow(-1, n) / pow(4, n)) * ((2 / (4 * n + 1)) + (2 / (4 * n + 2)) + (1 / (4 * n + 3)));
//Print secuential
printf("Resultado secuencial: %f\n", s);
gettimeofday(&fin, NULL);
//Result diff
printf("Diferencia resultados: %f\n", fabs(f - s));
//Time threads
printf("Tiempo por hilos: %f\n", restar_tiempo(&in, &mid));
//Secuential time
printf("Tiempo secuencial: %f\n", restar_tiempo(&mid, &fin));
//Time diff
printf("Diferencia tiempos: %f\n", restar_tiempo(&in, &mid) - restar_tiempo(&mid, &fin));
return 0;
}
I can compile everything without warnings, but when i execute the program, the result provided by the first thread is erratic, as it changes between executions (the rest of threads display 0 because they work with very little values).
Example with some added prints inside the thread function and after doing the join:
First execution:
This is i:0
This is i:1
This is i:2
This is i:3
//Inside thread funct
Thread result[2]: 0.000000
Thread result[2]: 0.000000
Thread result[3]: 0.000000
Thread result[0]: 3.141593
//After join
Partial result of thread 0: 3.141593
Partial result of thread 1: 0.000000
Partial result of thread 2: 0.000000
Partial result of thread 3: 0.000000
Total result: 3.141593
Sequential result: 3.141593
Difference results: 0.000000
Time per threads: 0.183857
Sequential time: 0.034788
Difference times: 0.149069
Second execution:
This is i:0
This is i:1
This is i:2
This is i:3
Thread result[2]: 0.000000
Thread result[0]: 6.470162
Thread result[0]: 6.470162
Thread result[3]: 0.000000
Partial result of thread 0: 6.470162
Partial result of thread 1: 0.000000
Partial result of thread 2: 0.000000
Partial result of thread 3: 0.000000
Total result: 6.470162
Sequential result: 3.141593
Difference results: 3.328570
Time per threads: 0.189794
Sequential time: 0.374017
Difference times: -0.184223
How can i make it so the sum works properly?
I think it has something to do with arg in the function _hilo, or the subsequent int cast with int a.
(Excuse the mix in languages, i speak spanish so most of the printfs are in said language. Dont mind them, the block with the results example has the traduction)
Okay i solved it but i dont know why it works like this fully or why this caused issues. I just deleted the free (p) statement and now it works like a charm. If someone can enlighten me on why this happens, i´ll be grateful.

Sum of the number 1 to 1000 using MPI

The summation is 49995000 in this case, but it should be 50005000. The number 10000 is missing. The following code makes use of 10 processors to compute the sum of numbers ranging from 1 to 1000. This aggregate is calculated by each of the processors, and the results are shown on the screen.
The final result of all processors' computations is gathered and aggregated by the zero processor, and the final result is shown in the output of the program.
I didn't figure out what the problem is. Please assist me in this matter.
#include <cstdio>
#include <cstdlib>
#include <mpi.h>
static int rank, nodes;
int main()
{
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &nodes);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Status status;
int ans = 0;
int total = 0;
int start = rank * 1000;
int end = start + 999;
for(int i = start; i <= end; i++) {
ans = ans + i;
}
if(rank != 0) {
MPI_Ssend(&ans, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
} else {
total = ans;
for(int j = 1; j < 10; j++) {
MPI_Recv(&ans, 1, MPI_INT, j, 0, MPI_COMM_WORLD, &status);
total += ans;
}
printf("Total is %d\n", total);
printf("Total Nodes is %d\n", nodes);
}
MPI_Finalize();
return 0;
}
The PBS Job file as followers,
#PBS -l nodes=2
#PBS -l walltime=00:02:00
#PBS -l select=10
cat $PBS_NODEFILE
NPROC=10
cd $PBS_O_WORKDIR
MPISIZE=$NPROC
MPIPROG=`basename $PBS_JOBNAME .pbs`
echo 'Running MPI program' $MPIPROG 'on' $MPISIZE 'processes'
echo 'Started at' `date`
echo '--------------------------------------------------------------------------------'
(time mpirun -n $MPISIZE ./$MPIPROG) 2>&1
echo '--------------------------------------------------------------------------------'
echo 'Finished at' `date`

Program does not take input from user to loop itself again.

I have this code down here and it working for calculating but it does not take the input of the user to do the loop again and calculate for the user again or cancel. the function is near the end with if(rank == 0) { ... }. I need help figure out what am I missing
#include <math.h> //include files
#include <stdio.h>
#include "mpi.h"
void printit()
{
printf("\n*********************************\n");
printf("Welcome to the pi calculator!\n");
printf("Programmer: K. Spry\n");
printf("You set the number of divisions\n");
printf("for estimating the integral: \n\tf(x)=4/(1+x^2)");
printf("\n");
printf("*********************************\n");
} //end printit
//function prototypes
int main(int argc, char* argv[])
{
double actual_pi = 3.141592653589793238462643;
//for comparison later
int n, rank, num_proc, i;
double temp_pi, calc_pi, int_size, part_sum, x;
char response = 'y';
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_proc);
if (rank == 0)
{
printit();
} /* I am root node, print out welcome */
while (response == 'y')
{
if (rank == 0)
{ /*I am root node*/
printf("__________________________________\n");
printf("\nEnter the number of intervals: (0 will exit)\n");
n = fgetc(stdin);
}
else
{
int_size = 1.0 / (double) n; //calcs interval size
part_sum = 0.0;
for (i = rank * n / num_proc; i <= (rank + 1)* n / num_proc; i += 1)
{ //calcs partial sums
x = int_size * ((double)i - 0.5);
part_sum += (4.0 / (1.0 + x*x));
}
temp_pi = int_size * part_sum;
//collects all partial sums computes pi
MPI_Reduce(&temp_pi,&calc_pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0)
{ /*I am server*/
printf("pi is approximately %f", calc_pi);
printf(". Error is %f", fabs(calc_pi - actual_pi));
printf("\n");
printf("_______________________________________");
printf("\n");
}
} //end else
if (rank == 0)
{ /*I am root node*/
printf("\nCompute with new intervals? (y/n)\n");
response = fgetc(stdin);
}
} //end while
MPI_Finalize(); //terminate MPI
return 0;
}
The problem I have is with the if inside the loop while that ask user to Compute with new intervals and user will input Y or N to response. The problem is when users do input, it stop working and never loop.
It behave as it should from what you coded :-).
The comment from ptb is the answer of your question.... But lets do it :-).
while (response == 'y')
{
if (rank == 0)
{ /*I am root node*/
printf("__________________________________\n");
printf("\nEnter the number of intervals: (0 will exit)\n");
n = fgetc(stdin);
}
/* here we have to: broadcast to all processes the value of response
in fact all processes have to wait that root get the new value and then
get this value from the root. Fortunately MPI_Broadcast is a blocking
opperation, so no MPI_Barrier are needed...*/
MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);
/* then your computation is done by every processes (in fact in your interval
boundaries you indeed take that process 0 has the first interval... i am not
sure your math a correct, I did not check them) */
int_size = 1.0 / (double) n; //calcs interval size
part_sum = 0.0;
for (i = rank * n / num_proc; i <= (rank + 1)* n / num_proc; i += 1)
{ //calcs partial sums
x = int_size * ((double)i - 0.5);
part_sum += (4.0 / (1.0 + x*x));
}
temp_pi = int_size * part_sum;
//collects all partial sums computes pi
MPI_Reduce(&temp_pi,&calc_pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0)
{ /*I am server*/
printf("pi is approximately %f", calc_pi);
printf(". Error is %f", fabs(calc_pi - actual_pi));
printf("\n");
printf("_______________________________________");
printf("\n");
}
if (rank == 0)
{ /*I am root node*/
printf("\nCompute with new intervals? (y/n)\n");
response = fgetc(stdin);
}
/* here we have to: broadcast to all processes the value of response
in fact all processes have to wait that root get the new value and then
get this value from the root. Fortunately MPI_Broadcast is a blocking
opperation, so no MPI_Barrier are needed..., lol same than with n...*/
MPI_Bcast(&response,1,MPI_CHAR,0,MPI_COMM_WORLD);
} //end while
I did not try to compile... so there is maybe some typos...

Segmentation fault (core dumped) in parallel computing

I am trying to code an AMPI to sum a 1d array in parallel. However, I am getting a segmentation fault (core dumped).
I tried to fix my function so many times but I could not find where the error is or how to fix it.
/* File: mpi_sum.c
* Compile as: mpicc -g -Wall -std=c99 -o mpi_sum mpi_sum.c -lm
* Run as: mpirun -n 40 ./mpi_sum
* Description: An MPI solution to sum a 1D array. */
int main(int argc, char *argv[]) {
int myID, numProcs; // myID for the index to know when should the cpu start and stop calculate
//numPro numper of cpu you need to do the calculation
double localSum; // this for one operation on one cpu
double parallelSum; // this for collecting the values of localsum
int length = 10000000; // this for how many num
double Fact = 1 ;
int i; // this for for loop
clock_t clockStart, clockEnd; // timer
srand(5); // Initialize MPI
MPI_Init(NULL, NULL); //Initialize MPI
MPI_Comm_size(MPI_COMM_WORLD, &numProcs); // Get size
MPI_Comm_rank(MPI_COMM_WORLD, &myID); // Get rank
localSum = 0.0; // the value for eash cpu is 0
int A = (length / numProcs)*((long)myID); // this is to make each cpu work on his area
int B = (length / numProcs)*((long)myID + 1); // this is to make each cpu work on his area
A ++; // add 1 to go to next num
B ++;
clockStart = clock(); // start the timer to see how much time it take
for (i = A; i < B; i++)
{
Fact = (1 / myID - 1/numProcs) / (1 - 1/numProcs);
localSum += Fact ;
}
MPI_Reduce(&localSum, &parallelSum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
clockEnd = clock();
if (myID == 0)
{
printf("Time to sum %d floats with MPI in parallel %3.5f seconds\n", length, (clockEnd - clockStart) / (float)CLOCKS_PER_SEC);
printf("The parallel sum: %f\n", parallelSum + 1);
}
MPI_Finalize();
return 0;
}
When I ran your code, my numProcs came up as 1 and the program crashed with
*** Process received signal ***
Signal: Floating point exception (8)
Signal code: Integer divide-by-zero (1)
Failing at address: 0x400af9
[ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x10330)[0x7f8bb13d2330]
[ 1] ./mpi_sum[0x400af9]
[ 2] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f8bb101af45]
[ 3] ./mpi_sum[0x400919]
*** End of error message ***
Floating point exception (core dumped)
on the line
Fact = (1 / myID - 1/numProcs) / (1 - 1/numProcs);
because we had a zero in the denominator.
Since you are getting a different error, may I suggest putting in a bunch of:
printf("%d\n", __LINE__); fflush(stdout);
statements to get an idea where it is crashing?

Why the variable time1 becoming Zero?

When I am getting some problem why time1 variable getting zero. right after calculation of floor.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main()
{
int curfl = 0, destfl, floor;
int time1, high, speed;
high = 3;
speed = 5;
while(1)
{
printf("Currently the elevator is at floor number = %d\n", curfl);
printf("Enter the floor number between 0-25 : ");
scanf("%d", &destfl);
if(destfl > curfl)
{
floor = destfl - curfl;
/*****************************/
time1 = (floor * (high / speed)); //variable become zero here
/*****************************/
printf("Elevator will take %d second to reach %d (st, nd, rd) floor \n", time1, destfl);
while(curfl != destfl)
{
Sleep(1000 * 3 / 5);
curfl++;
printf("You are at floor number %d \n", curfl);
}
printf("Door opening \n");
Sleep(10000);
printf("Door Closed\n");
}
else if(destfl > curfl)
{
floor = curfl - destfl;
time1 = (floor * (3 / 5));
printf("Elevator will take %d second to reach %d (st, nd, rd) floor \n", time1, destfl);
while(curfl != destfl)
{
Sleep(1000 * 3 / 5);
curfl--;
printf("You are at floor number %d \n", curfl);
}
printf("Door opening \n");
Sleep(10000);
printf("Door Closed\n");
}
else{
printf("You are the same floor. Please getout from the elevator \n");
}
}
// printf("Hello world!\n");
return 0;
}
You are doing integer calculations. Switch to something that handles fractions.
You are running into integer division. When you do arithmetic on integers, and the result will also be an integer. So something like 1 / 3 = 0 in integer-land. So when you do (high / speed), the temporary result will be an integer, and if the answer is some decimal < 1, the result will be truncate simply to 0.
To fix this, you should change the code to use float or double instead int.
calculate time1 like follows :
int curfl = 0, destfl, floor;
int high;
float speed, time1;
................................
time1 = (floor * (high / speed));
It looks like its for an embedded device. So don't know how it supports floating point operation.
if it does not support, pickup a divide algorithm, declare a type like following :
struct myfloat{
int precision;
int exponent;
}
and then write a divide function like :
struct myfloat * divide(int a, int b) /* gives result for a/b */

Resources