Control some code to be executed once in MPI - c

I can't control how to make to execute some code once using mpi
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#define N 10
#define ITERS 1
// N and ITERS might be input arguments
double **A;
int times = 0;
void initialize (double **A)
{
int i,j;
for(i =0; i < N+2 ; i++){
for(j =0; j < N+2 ; j++){
if(i== 0 || j == 0 || i == (N+1) || j == (N +1) )
A[i][j] = 0.0;
else
A[i][j] = rand() % 10 + 1;
}
}
}
int main(int argc, char * argv[]){
int MyProc, size,tag=1;
char msg='A', msg_recpt;
MPI_Status status;
double **received_array;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &MyProc);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Process # %d started \n", MyProc);
MPI_Barrier(MPI_COMM_WORLD);
int i;
/******Make it once*******/
if(times == 0){
printf("One time\n");
A = malloc((N+2) * sizeof(double *));
for (i=0; i<N+2; i++) {
A[i] = malloc((N+2) * sizeof(double));
}
initialize(A);
times ++;
}
/*************/
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
I've tried with times variable as a flag but the make it once section it's executed once per process...everethig I've tried it's executed once per process ,I don't know what to try, I can't make it using the rank of teh process because I need the first procees to arrive executes the once section.

Related

Why do I get different values in debug mode?

My program supposed to calculate the matrix product (multiplication) of 2 given matrices using multithreading - each thread calculates one column.
The problem is - when I run it from the terminal, I'm getting few zeros columns. I used debugger to see where the problem is - but at the debugger it works fine every time! I can't figure out where the problem is
How is it possible that I'm getting different values when debugging vs regular execution?
I tried some "simple solutions" from online searching:
reset the linux virtual machine
reset VSCode
and i don't getting any errors or memory leaks but i have no idea what to do further
my code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <sys/stat.h>
#include <pthread.h>
int MATRIX_DIM=3; //default
int **RESULT_MAT;
struct calcCol{
int **matA;
int **matB;
int **matC;
int dim;
int i;
};
int ijMult(int **matA, int **matB,int dim, int i, int j);
void* colMatCalc(void* s);
void printMatrix(int **mat);
void getMatrix(int **mat);
void freeMatrices(int **matA, int **matB, int **matC);
void* printThreadId(void* arg){
int i = *(int*)arg;
printf("Thread id: %d \n", i);
pthread_exit(NULL);
}
int main(){
pthread_t tid[MATRIX_DIM];
int args[MATRIX_DIM];
pthread_attr_t attr;
pthread_attr_init(&attr);
printf("Enter enter MATRIX_DIM (number between 1 and 10) \n");
scanf("%d",&MATRIX_DIM);
if(MATRIX_DIM>10 || MATRIX_DIM<1)
MATRIX_DIM=3; //default value
//memory allocation for matrices
int **matA = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) matA[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
int **matB = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) matB[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
RESULT_MAT = (int **)malloc(MATRIX_DIM * sizeof(int*));
for(int i = 0; i < MATRIX_DIM; i++) RESULT_MAT[i] = (int *)malloc(MATRIX_DIM * sizeof(int));
struct calcCol s;
s.matA = matA;
s.matB = matB;
s.matC=RESULT_MAT;
s.dim=MATRIX_DIM;
s.i=0;
printf("Enter elements of first matrix \n");
getMatrix(matA);
printf("Enter elements of second matrix \n");
getMatrix(matB);
for(int i=0 ; i<MATRIX_DIM ; i++)
{
args[i]=i;
s.i=i;
pthread_create(&tid[i], &attr, colMatCalc, &s);
}
for(int i=0 ; i<MATRIX_DIM ; i++)
{
if(pthread_join(tid[i], NULL)!=0)
{
perror("pthread_join faild.");
exit(EXIT_FAILURE);
}
printf("Thread %d is terminated.\n", *(int*)(&args[i]));
}
printf("All threads are terminated!\n");
printf("Product of the matrices: \n");
printMatrix(RESULT_MAT);
freeMatrices(matA, matB, RESULT_MAT);
return 0;
}
//calculating (i,j) of the result matrix
int ijMult(int **matA, int **matB, int dim, int i, int j)
{
int sum = 0;
for(int k = 0 ; k < MATRIX_DIM ; k++)
sum = sum + (matA[i][k]*matB[k][j]);
return sum;
}
//calculating the 'i' column of the result matrix
void* colMatCalc(void* arg)
{
struct calcCol s = *(struct calcCol*)arg;
for(int k = 0 ; k < s.dim ; k++)
s.matC[k][s.i] = ijMult(s.matA, s.matB,s.dim, k, s.i);
return 0;
}
void printMatrix(int **mat)
{
for(int i = 0 ; i < MATRIX_DIM ; i++)
{
for(int j = 0 ; j < MATRIX_DIM ; j++)
{
printf("%d \t", mat[i][j]);
}
printf("\n");
}
}
void getMatrix(int **mat)
{
for(int i=0 ; i<MATRIX_DIM ; i++)
{
for(int j=0 ; j<MATRIX_DIM ; j++)
{
scanf("%d",&mat[i][j]);
}
}
}
void freeMatrices(int **matA, int **matB, int **matC)
{
for(int i=0 ; i < MATRIX_DIM ; i++)
{
free(matA[i]);
free(matB[i]);
free(RESULT_MAT[i]);
}
free(matA);
free(matB);
free(RESULT_MAT);
}
I know i don't need to paste the entire code, but i really don't know where is the tricky part...cause again- when i'm in debug mode it works fine.
Input: 3 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6
7 8 9 Expected output 30 36 42 66 81 96
102 126 150
Actual output: same but with zeros column instead (different columns each time)
Thank you.
The problem is with variable s which is shared across all the threads, that is
s.i=i;
When you update s in the loop, every thread will be pointing to latest contents of s.
What you can do is have different instance to each thread as below.
for(int i=0 ; i<MATRIX_DIM ; i++)
{
struct calcCol *s = malloc(sizeof(*s));
s->matA = matA;
s->matB = matB;
s->matC=RESULT_MAT;
s->dim=MATRIX_DIM;
s->i=0;
args[i]=i;
s->i=i;
pthread_create(&tid[i], &attr, colMatCalc, s);
}
With that when you update the content of *s it won't affect other thread's execution.
Make sure you free it once thread is finished its execution.

Passing a parameter to a thread but get I get completely different results than anticipated

I am completely new to C, so excuse me for my lack of knowledge. I am trying to make 4 threads that will each generate a number between 100-199 200-299 300-399 and 400-499 for each of the threads respectively. However when I pass my parameter interv which is a struct type with two int values, I get something completely different on the other side. For example when I send in 100 and 199, I get 0 instead of 199 and -13216 instead of 100. I am not sure where exactly the problem is, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 4
int sum; /* global variable shared by thread(s) */
pthread_mutex_t counter_lock = PTHREAD_MUTEX_INITIALIZER;
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
typedef struct interval {
int min;
int max;
} interval;
void *runner(struct interval *param); /* threads call this function */
/*
*
*/
int main(int argc, char *argv[]) {
pthread_t workers[NUM_THREADS];
interval *interv;
interv->max = 199;
interv->min = 100;
/* create the thread */
printf("min = %d max = %d \n",interv->min,interv->max);
for (int i = 0; i < NUM_THREADS; i++) {
printf("min = %d max = %d \n",interv->min,interv->max);
pthread_create(&workers[i],NULL,runner,&interv);
interv->min += 100;
interv->max += 100;
/* wait for the thread to exit */
pthread_join(&workers[i],NULL);
}
printf("sum = %d\n",sum);
return (0);
}
/* The thread will begin control in this function */
void *runner(struct interval *param) {
int n, array[100], list_sum, counter;
printf("min = %d max = %d \n",param->min,param->max);
for (int i; i < 100; i++) {
n = rand() % (param->max + 1 - param->min) + param->min;
array[i] = n;
list_sum += n;
}
qsort(array, 100, sizeof(int), cmpfunc);
for (int i; i < 100; i++) {
counter += 1;
if (counter == 10) {
counter = 0;
}
}
pthread_mutex_lock(&counter_lock);
sum += list_sum;
pthread_mutex_unlock(&counter_lock);
pthread_exit(0);
}
UPDATED:
So I did not get the result I expected when the program compiled, so I re-wrote most of my code. Although now, again, I am getting some strange behavior and I am not sure why.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 1
#define NUM_ELEMENTS 10
//Sum computed buy the background thread
int total = 0;
int counter = 0;
struct sum_runner_struct {
int min;
int max;
int array[NUM_ELEMENTS];
int answer;
};
//Thread function to generate a sum of 0 to N
void* runner(void* arg) {
struct sum_runner_struct *arg_struct = (struct sum_runner_struct*) arg;
int n, sum;
for (int i = 0; i<NUM_ELEMENTS; i++) {
n = rand()%(arg_struct->max + 1 - arg_struct->min) + arg_struct->min;
printf("%d ",n);
arg_struct->array[i] = n;
}
printf("\n");
for (int i = 0; i<NUM_ELEMENTS; i++) {
sum = sum + arg_struct->array[i];
printf("%d ", arg_struct->array[i]);
counter += 1;
if (counter == 10) {
printf("\n");
counter = 0;
}
}
printf("Sum: %d\n",sum);
arg_struct->answer = sum;
pthread_exit(0);
}
int main(int argc, char **argv) {
int INTERVALS[4][2] = {{100,199},{200,299},{300,399},{400,499}};
struct sum_runner_struct args[NUM_THREADS];
// Launch threads
pthread_t tids[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
args[i].min = INTERVALS[i][0];
args[i].max = INTERVALS[i][1];
//Create attributes
pthread_attr_t attr;
pthread_attr_init(&attr);
//Create Thread
pthread_create(&tids[i], &attr, runner, &args[i]);
}
//Wait until thread is done its work
for (int i = 0; i < NUM_THREADS; i++) {
pthread_join(tids[i], NULL);
printf("Sum of thread %d is %d\n", i, args[i].answer);
total += args[i].answer;
}
printf("Sum is %d\n", total);
}
Before you comment on my random number generator, I know that it is not the best solution as of now, but that is not my issue. My issue is when I add the numbers in the array for a thread I get a number that is bigger by 6 integers. I am not sure why this happens.
For example when I run the program with a single thread to generate 10 elements I would get something like this:
133 143 162 129 100 108 152 156 156 119
133 143 162 129 100 108 152 156 156 119
Sum: 1364
Sum of thread 0 is 1364
Sum is 1364
RUN SUCCESSFUL (total time: 57ms)
Note that I printed the array twice hence why there are two lines of the same array. As you can see (I think I added them up right) if you add the numbers in the array you would get 1358, not 1364. I am not sure what causes this.
Okay I found the issue, I am not sure exactly why, but when I initialize
int n, sum;
for some reason sum value is initialized to 6. Can anyone explain why this happens?

reading in a file c small error big problems

I am trying to fill 2 matrices from 2 data text files but the compiler is telling me I have conflicting types for the "infiles" (1&2) but if I take out FILE I get a casting error and if I take out infile =fopen i get no output at all for matrices but it does compile. nothing seems to work right
the problem code:
FILE *infile1;
FILE *infile2;
*infile1 = (int)fopen("m1.dat","r");
*infile2 = (int)fopen("m2.dat","r");
full code:
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
//using namespace std;
//ifstream infile1 ("m1.dat");
//ifstream infile2 ("m2.dat");
int infile1 = (int)fopen("m1.dat","r");
int infile2 = (int)fopen("m2.dat","r");
FILE *infile1;
FILE *infile2;
//if (!infile1) //testing files
// cerr << "Error: could not open input file 1\n";
//if (!infile2) //testing files
//cerr << "Error: could not open input file 2\n";
if (!infile1) //testing files
fprintf(stderr, "file 1 missing\n");
exit(1);
if (!infile2) //testing files
fprintf(stderr, "file 2 missing\n");
exit(1);
int i, j, size1, size2 =0;
//infile1 >> size1;
//infile2 >> size2;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
//infile1 >> A[i][j];
// infile2 >> B[i][j];
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Edit: Latest version of code. Still just outputs nothing to the screen. Even have a printf that should run right before it closes and that doesnt even work. The only thing I did change from a working versiion(it used to do it correctly) was that the things related to the opening of the file were in C++ and I changed it to C. No idea why I don't get any errors though. Here is my latest full code. the output looks like this http://tinypic.com/r/21185u9/9
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#define M 4
#define K 4
#define N 4
void *runner(void *param); /* the thread */
int A [M][K];
int B [K][N];
int C [M][N];
struct v {
int i; // row
int j; // column
};
int main(int argc, char *argv[]) {
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
if (infile2 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 2 Missing");
exit(1);
int i, j, size1, size2 =0;
fscanf(infile1,"%d",&size1);
fscanf(infile2,"%d",&size2);
float s = (float)size1;
int dim = (int)sqrt(s);
for(i=0;i<M;i++){
for(j=0;j<N;j++){
fscanf(infile1,"%d",&A[i][j]);
fscanf(infile2,"%d",&B[i][j]);
}
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");
printf("%d \t",A[i][j]);
}
}
printf("\n\n");
for(i=0;i<M;i++){
for(j=0;j<N;j++){
if ((j % dim)==0) printf("\n");;
printf("%d \t",B[i][j]);
}
}
printf("\n\n");
int count = 0;
for(i = 0; i < M; i++) { //column
for(j = 0; j < N; j++) { //row
//Assign a row and column for each thread
struct v *data = (struct v *) malloc(sizeof(struct v));
data->i = i;
data->j = j;
// Now create the thread passing it data as a parameter
pthread_t tid; //Thread ID
pthread_attr_t attr; //Set of thread attributes
//Get the default attributes
pthread_attr_init(&attr);
//Create the thread
pthread_create(&tid,&attr,runner,data);
//Make sure the parent waits for all thread to complete
pthread_join(tid, NULL);
count++;
}
}
//Print out the resulting matrix
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
printf("\n \n");
printf("program ran");
fclose(infile1);
fclose(infile2);
return 0;
}
//The thread will begin control in this function
void *runner(void *param) {
struct v *data = (struct v*)param; // the structure that holds our data
int n, sum = 0; //the counter and sum
//Row multiplied by column
for(n = 0; n< K; n++){
sum += A[data->i][n] * B[n][data->j];
}
//assign the sum to its coordinate
C[data->i][data->j] = sum;
pthread_exit(0);
}
Your error comes from declaring the return value from the file open function incorrectly.
Instead of using your problem code, use:
FILE *infile1 = fopen("m1.dat","r");
FILE *infile2 = fopen("m2.dat","r");
It declares infile1 and infile2 as pointers to the FILE type with the values properly set depending on how successful the file can be opened. In simple terms, call infile1 and infile2 as file handles.
If you want an integer value as the return value, you can look into the open() function instead of fopen(), but fopen() works well in your case.
If you check the exit status of your edited code, you will find that it is 1 due to exiting after the first file check. In your code you have:
if (infile1 == NULL) //testing files
//if (!infile1) //testing files
//fprintf(stderr, "file 1 missing\n");
perror("File 1 Missing");
exit(1);
Which will run the exit(1) function every time (even if infile1 is OK). You need to properly contain exit within the scope of your check with {...}. e.g.:
if (infile1 == NULL) { //testing files
perror ("File 1 Missing");
exit (1);
}
and the same for infile2. I have not checked the remainder of your code.

Segmentation fault without altering my program

I was trying to write a program that calculates prime numbers using threads and the program was working but not giving the desired results (it was telling all numbers were prime numbers). Today I tried to run the program again and I'm getting a segmentation fault even though I didn't alter my program. I tried using gdb to find when it was happening and I think it's happening on the pthread_join function.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=0; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*)arg;
int idx = *idxp;
int start = idx* elements_per_thread;
int finish = (idx+1)*elements_per_thread-1;
int i;
for(i=start; i<finish; i++)
if(!isPrime(i))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id = (int *)malloc(n_threads*sizeof(int));
// compute primes
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
Problem solved. Correct code below.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int n_threads; // number of threads
int* numbers; // array of numbers
int elements_per_thread;
int isPrime(int n){
int i = 0;
for(i=2; i < n; i++)
if(n%i == 0)
return 0;
return 1;
}
void * threadPrime(void * arg){
int* idxp = (int*) arg;
int idx = *idxp;
int start = idx*elements_per_thread;
int finish = (idx+1)*elements_per_thread;
int i;
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
pthread_exit(NULL);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("usage: %s largest_number number_threads\n", argv[0]);
return 1;
}
int largest_number = atoi(argv[1]); // value of the largest number to test for primality
int n_numbers = largest_number-1; // number of numbers to test
n_threads = atoi(argv[2]);
// create and fill vector of numbers to test
numbers = (int *)malloc(n_numbers*sizeof(int)) ; // allocate a vector for n_numbers integers
int i;
for (i = 2; i <= largest_number; i++)
numbers[i-2] = i;
int* id;
id = (int *)malloc(n_threads*sizeof(int));
// compute primeselements_per_thread = n_numbers/n_threads;
elements_per_thread = (n_numbers/n_threads)+1;
pthread_t* thid = malloc(n_threads*sizeof(*thid));
for(i=0;i<n_threads;i++){
id[i] = i;
if(pthread_create(&thid[i],NULL,threadPrime,(void*)(id+i)) != 0){
printf("Erro\n");
exit(0);
}
}
for(i=0;i<n_threads;i++){
if(pthread_join(thid[i],NULL) != 0){
printf("Erro\n");
exit(0);
}
}
// print result
printf("Primes:");
int n_primes = 0;
for (i = 0; i < n_numbers; i++)
if (numbers[i]) {
n_primes++;
printf (" %d", numbers[i]);
}
printf("\nTotal: %d primes\n", n_primes);
return 0;
}
There are a number of issues:
1) The starting index for the loop should be 2. Otherwise, you are going to have divide by zero error here:
for(i=0; i < n; i++) // should be i=2
if(n%i == 0)
return 0;
2) elements_per_thread is not set at all. So it's going to be 0 (since it's a global variable) and the loops in thread function will never be called. Set it in main():
elements_per_thread = n_numbers/n_threads;
3) When you call isPrime() you are passing i. But you really wanted to pass numbers[i]. You also want to include the finish in the primality test. So it should be
for(i=start; i<=finish; i++)
if(!isPrime(numbers[i]))
numbers[i]=0;
4) The allocation for thread array is wrong. It should be
pthread_t* thid = malloc(n_threads * sizeof *thid);
There are more efficient ways to test primes (e.g. you only need to check upto n/2 to see if it's prime). But once you fix the above issues, you'll have a working code and think about improving it later.
You didn't allocate the right amount of memory for thid. This is the main reason for your segmentation fault.
pthread_t* thid = (pthread_t *)malloc(n_threads*sizeof(int));
should be
pthread_t* thid = malloc(n_threads*sizeof(p_thread));
(you don't need to cast malloc in C)
This is why I don't usually use an explicit type as the operand of sizeof, and instead just use the variable name so that the compiler can deduce the type itself.
pthread_t* thid = malloc(n_threads*sizeof(*thid));

MPI partition array into blocks and Send

I am trying to find a maximum element of an array using MPI in C language. I have to compare the time it takes to send and calculation of the maximum using vs MPI_Scatter functions. MPI_Send: Here' the code for the MPI_Scatter function it works great:
#include "mpi.h"
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#define lim 20
//returns "a-b" in seconds
double timeval_diff(struct timeval *a, struct timeval *b)
{
return
(double)(a->tv_sec + (double)a->tv_usec/1000000) -
(double)(b->tv_sec + (double)b->tv_usec/1000000);
}
//Array to be divided among the processes
int buf[lim]=
{27,24,3,8,45,10,50,15,10,11,9,48,69,25,19,29,61,72,93,20};
int buf2[lim];
int buf3[lim];
int max;
int main(int argc, char *argv[])
{
struct timeval t_ini, t_fin;
double secs;
int n, myid, numprocs, i,j;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,"Process %d in %s\n",myid, processor_name);
/*Check Border Conditions */
n=lim/numprocs;
gettimeofday(&t_ini, NULL); //take the time before sending the buffer with Scatter
MPI_Scatter(buf,n, MPI_INT,buf2,n,MPI_INT, 0, MPI_COMM_WORLD);
gettimeofday(&t_fin, NULL);//take the time to complete the send routine
secs = timeval_diff(&t_fin, &t_ini);
MPI_Reduce(buf2,buf3,n, MPI_INT, MPI_MAX, 0,MPI_COMM_WORLD);
if (myid == 0)
{ max = buf3[0];
for (i=1; i<n ; i++)
if (max < buf3[i]) max = buf3[i];
for (i=0; i<n ; i++)
printf("Buf3[%d]= %d \n", i, buf3[i]);
printf("Max number of the array is: %d \n", max);
}
for (i=0; i<n ; i++){
printf("%d,Buf2[%d]= %d \n",myid, i,buf2[i]);}
printf("%.16g milliseconds\n", secs * 1000.0);
MPI_Finalize();
return 0;
}
The problem comes when I try to do the same procedure with the MPI_Send function because I calculated the maximum array elements, what am I doing wrong?:
#include "mpi.h"
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#define lim 20
//returns "a-b" in seconds
double timeval_diff(struct timeval *a, struct timeval *b)
{
return
(double)(a->tv_sec + (double)a->tv_usec/1000000) -
(double)(b->tv_sec + (double)b->tv_usec/1000000);
}
//Array to be divided among the processes
int buf[lim]=
{27,24,3,8,45,10,50,15,10,11,9,48,69,25,19,29,61,72,93,20};
int buf2[lim];
int buf3[lim];
int max;
int main(int argc, char *argv[])
{
struct timeval t_ini, t_fin;
double secs;
int n, myid, numprocs, i,j;
int namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
MPI_Get_processor_name(processor_name,&namelen);
fprintf(stderr,"Process %d in %s\n",myid, processor_name);
/*Check Border Conditions */
n=lim/numprocs;
gettimeofday(&t_ini, NULL); //take the time before sending the buffer with Scatter
for (j=0;j<n;j++){
MPI_Send(buf, lim, MPI_INT, 1, 111, MPI_COMM_WORLD);
}
gettimeofday(&t_fin, NULL);//take the time to complete the send routine
secs = timeval_diff(&t_fin, &t_ini);
if (myid == 0)
{ max = buf3[0];
for (i=1; i<n ; i++)
if (max < buf3[i]) max = buf3[i];
for (i=0; i<n ; i++)
printf("Buf3[%d]= %d \n", i, buf3[i]);
printf("Max number of the array is: %d \n", max);
}
for (i=0; i<n ; i++){
printf("%d,Buf2[%d]= %d \n",myid, i,buf2[i]);}
printf("%.16g milliseconds\n", secs * 1000.0);
MPI_Finalize();
return 0;
}
I wasted some hours watching Where is the fault but I can not see it ... Any help?
you are missing the MPI_Recv call on the other end of your MPI_Send call, these kind of functions are more low level as opposed to the collective scatter, gather, reduce and broadcast functions

Resources