Please help explain fork() in Operating System [duplicate] - multithreading

This question already has answers here:
How does fork() work?
(5 answers)
Closed 5 years ago.
Given the following piece of code:
main(int argc, char ** argv)
{
int child = fork();
int c = 5;
if (child == 0)
{
c += 5;
}
else
{
child = fork();
c += 10;
if (child)
c += 5;
}
}
How many different copies of the variable c are there? What are their values?
So, the answer turned out to be there are three (3) processes:
c value of parent process is 20,
c value of child1 process is 10,
c value of child2 process is 15,
Can someone please help me explain this in detail? Line by line would be great!
I see that there is another question addressing fork(), but I want to understand this lines of code specifically and how the answers came out like that.

The first child process executes:
int child = fork();
int c = 5;
/* since child == 0 */
c += 5;
The second child executes:
int child = fork();
int c = 5;
/* since child != 0 */
child = fork();
c += 10;
/* child == 0 now */
The parent process executes:
int child = fork();
int c = 5;
/* since child != 0 */
child = fork();
c += 10;
/* since child != 0 */
c += 5;

Related

MPI4PY: ring communication with neighbor_alltoallw

Please Help!
I am using MPI (= Message Passing Interface) in python for a ring communication, which means that every rank are sending and receiving from each other. I know one way to realize this is by using for instance MPI.COMM_WORLD.issend()and MPI.COMM_WORLD.recv(), this is working and done.
Now I want to realize the same Output on a different way by using MPI.Topocomm.Neighbor_alltoallw but this is not working. I wrote a C Code and is working there, so the same output can be reached with this function, but when I implement this in python it is not working. Please find below the C Code and the Python Code
The definition of the Function says (mpi4py Package for Python):
Neighbor_alltoallw(...)
Topocomm.Neighbor_alltoallw(self, sendbuf, recvbuf)
Neighbor All-to-All Generalized
I do not understand following things:
why is recbuf not a return value? it seems to be an argument here
how can this be implmented for a ring communication in Python?
Thank you for your time and support!
my working C Code:
#include <stdio.h>
#include <mpi.h>
#define to_right 201
#define max_dims 1
int main (int argc, char *argv[])
{
int my_rank, size;
int snd_buf, rcv_buf;
int right, left;
int sum, i;
MPI_Comm new_comm;
int dims[max_dims],
periods[max_dims],
reorder;
MPI_Aint snd_displs[2], rcv_displs[2];
int snd_counts[2], rcv_counts[2];
MPI_Datatype snd_types[2], rcv_types[2];
MPI_Status status;
MPI_Request request;
MPI_Init(&argc, &argv);
/* Get process info. */
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* Set cartesian topology. */
dims[0] = size;
periods[0] = 1;
reorder = 1;
MPI_Cart_create(MPI_COMM_WORLD, max_dims, dims, periods,
reorder,&new_comm);
/* Get coords */
MPI_Comm_rank(new_comm, &my_rank);
/* MPI_Cart_coords(new_comm, my_rank, max_dims, my_coords); */
/* Get nearest neighbour rank. */
MPI_Cart_shift(new_comm, 0, 1, &left, &right);
/* Compute global sum. */
sum = 0;
snd_buf = my_rank;
rcv_buf = -1000; /* unused value, should be overwritten by first MPI_Recv; only for test purpose */
rcv_counts[0] = 1; MPI_Get_address(&rcv_buf, &rcv_displs[0]); snd_types[0] = MPI_INT;
rcv_counts[1] = 0; rcv_displs[1] = 0 /*unused*/; snd_types[1] = MPI_INT;
snd_counts[0] = 0; snd_displs[0] = 0 /*unused*/; rcv_types[0] = MPI_INT;
snd_counts[1] = 1; MPI_Get_address(&snd_buf, &snd_displs[1]); rcv_types[1] = MPI_INT;
for( i = 0; i < size; i++)
{
/* Substituted by MPI_Neighbor_alltoallw() :
MPI_Issend(&snd_buf, 1, MPI_INT, right, to_right,
new_comm, &request);
MPI_Recv(&rcv_buf, 1, MPI_INT, left, to_right,
new_comm, &status);
MPI_Wait(&request, &status);
*/
MPI_Neighbor_alltoallw(MPI_BOTTOM, snd_counts, snd_displs, snd_types,
MPI_BOTTOM, rcv_counts, rcv_displs, rcv_types, new_comm);
snd_buf = rcv_buf;
sum += rcv_buf;
}
printf ("PE%i:\tSum = %i\n", my_rank, sum);
MPI_Finalize();
}
My not working Python Code:
from mpi4py import MPI
size = MPI.COMM_WORLD.Get_size()
my_rank = MPI.COMM_WORLD.Get_rank()
to_right =201
max_dims=1
dims = [max_dims]
periods=[max_dims]
dims[0]=size
periods[0]=1
reorder = True
new_comm=MPI.Intracomm.Create_cart(MPI.COMM_WORLD,dims,periods,True)
my_rank= new_comm.Get_rank()
left_right= MPI.Cartcomm.Shift(new_comm,0,1)
left=left_right[0]
right=left_right[1]
sum=0
snd_buf=my_rank
rcv_buf=-1000 #unused value, should be overwritten, only for test purpose
for counter in range(0,size):
MPI.Topocomm.Neighbor_alltoallw(new_comm,snd_buf,rcv_buf)
snd_buf=rcv_buf
sum=sum+rcv_buf
print('PE ', my_rank,'sum=',sum)

when i input a char,mainthread and child thread all return?

//see thd code.why child will and process,c = NULL?
void* process(void* arg){
char c = getchar();
printf("process,c = %c\n",c);
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,process,NULL);
char c = getchar();
printf("main,c = %c\n",c);
pthread_join(tid,NULL);
printf("over\n");
return 0;
}
//and main,c has value,and process,c not have value
getchar() only returns each character of input only once. You have two threads that both call getchar(). When a character arrives, one of them returns that character while the other thread waits for the next character.

calculate determinant of matrix with thread

ı want to calculate determinant of matrix with thread but i have a error "term does not eveluate to a function taking 0 arguments" ı want to solve big matrix with thread and parsing matrix,what can ı do
int determinant(int f[1000][1000], int x)
{
int pr, c[1000], d = 0, b[1000][1000], j, p, q, t;
if (x == 2)
{
d = 0;
d = (f[1][1] * f[2][2]) - (f[1][2] * f[2][1]);
return(d);
}
else
{
for (j = 1; j <= x; j++)
{
int r = 1, s = 1;
for (p = 1; p <= x; p++)
{
for (q = 1; q <= x; q++)
{
if (p != 1 && q != j)
{
b[r][s] = f[p][q];
s++;
if (s > x - 1)
{
r++;
s = 1;
}
}
}
}
for (t = 1, pr = 1; t <= (1 + j); t++)
pr = (-1)*pr;
c[j] = pr*determinant(b, x - 1);
}
for (j = 1, d = 0; j <= x; j++)
{
d = d + (f[1][j] * c[j]);
}
return(d);
}
}
int main()
{
srand(time_t(NULL));
int i, j;
printf("\n\nEnter order of matrix : ");
scanf_s("%d", &m);
printf("\nEnter the elements of matrix\n");
for (i = 1; i <= m; i++)
{
for (j = 1; j <= m; j++)
{
a[i][j] = rand() % 10;
}
}
thread t(determinant(a, m));
t.join();
printf("\n Determinant of Matrix A is %d .", determinant(a, m));
}
The immediate problem is that here: thread t(determinant(a, m)); you pass the result of calling determinant(a, m) as the function to execute, and zero arguments to call that function with - but an int is not a function or other callable object, which is what the error you got complains about.
std::thread's constructor takes the function to run and the arguments to supply separately, so you would need to call std::thread(determinant, a, m).
Now we have another problem, std::thread doesn't provide a way to retrieve the return value, and so you calculate it again here: printf("\n Determinant of Matrix A is %d .", determinant(a, m));.
To fix this, we can use std::async from the <future> header, which will manage the thread handling for us, and lets us retrieve the result later:
auto result = std::async(std::launch::async, determinant, a, m);
int det = result.get()
This will run determinant(a,m) on a new thread, and return a std::future<int> into which the return value may eventually be placed.
We can then try to retrieve that value with std::future::get(), which will block until the value can be retrieved (or until an exception occurs in the thread).
In this example, we still execute determinant in a pretty serial fashion, since we delegate the work to a thread, then wait for that thread to finish its work before continuing.
However we are now free to store the future, and defer calling std::future::get() until we actually need the value, potentially much later in your program.
There are a few other problems in the rest of your code:
all your array indexing is off by one (array indices run from 0 to N-1 in C and C++)
a few of the variables you're using don't exist (like a and m)
C-arrays are passed by pointer, so if you ever change the code not to block on the thread right there, the array will go out of scope and your thread may read garbage from the dangling pointer. If you use a proper container like std::array or std::vector, you can pass it by value so your thread will own the data to operate on for its entire lifetime.

possible race condition in pthread application (unable to detect)

Here is my problem with a pthread code. When I run the following commands:
./run 1
./run 2
./run 4
the first two commands (one thread and two threads) generate the same output. However with 4 threads (third command), I see different outputs.
Now when I run the following commands
valgrind --tool=helgrind ./run 1
valgrind --tool=helgrind ./run 2
valgrind --tool=helgrind ./run 4
They generate the same outputs. The output values are correct though.
How can I investigate further?
The code looks like
int main(int argc,char *argv[])
{
// Barrier initialization
if(pthread_barrier_init(&barr, NULL, threads)) {
printf("Could not create a barrier\n");
return -1;
}
int t;
for(t = 0; t < threads; ++t) {
printf("In main: creating thread %ld\n", t);
if(pthread_create(&td[t], NULL, &foo, (void*)t)) {
printf("Could not create thread %d\n", t);
return -1;
}
}
...
}
void * foo(void *threadid)
{
long tid = (long)threadid;
for ( i = (tid*n/threads)+1; i <= (tid+1)*n/threads; i++ ) {
printf( "Thread %d, i=%d\n", tid, i );
for(largest = i, j = i+1; j <= n; j++) {
if(abs( a[j][i] ) > abs( a[largest][i] ))
largest = j;
}
for(k = i; k <= n+1; k++)
SWAP_DOUBLE( a[largest][k], a[i][k]);
for( j = i+1; j <= n; j++) {
for( k = n+1; k >= i; k--)
a[j][k] = a[j][k]-a[i][k]*a[j][i]/a[i][i];
}
}
int rc = pthread_barrier_wait(&barr);
if(rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) {
printf("Could not wait on barrier\n");
exit(-1);
}
printf("after barrier\n");
...
}
The main loop (which iterate over i in foo()) is divided by the number of threads. assume all variables are defined properly since as I said there is no problem with 1 and 2 threads.
I'm not entirely sure what's going on, since you haven't given a complete compilable program to experiment with, but it's clear that each of the threads is reading/writing from sections of a that it aren't assigned to it, so you have race conditions all over the place. You are swapping sections of a so I'm not sure you can parallelize this algorithm as it stands.

Broken pipes in C -- pipe(), fork(), exec() program

I need to write a simple program: There will be a Parent and a few programs [children] (started via execl in Parent). Children communicate to one another in this way: Child I sens to Parent number J, Parent sends a message (something like -- "there is a message to you") to J, J send to Parent number K etc. etc.
And there is a problem -- my program (tested by strace command) tries to send a message to child and there comes the broken pipe error.
I will be grateful if somebody looks through the code and tells me what's wrong:
Here is the code:
/**
* Arbiter zabawy w Losia
*
wersja: Alfa 3b
początek edycji 25.01.2009
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "err.h"
pid_t pid;
FILE *a;
int main ()
{
// my N players
int N;
N = 10;
//write -- writing from parent to child
//read -- reading from child
int rurka_write[N+1][2];
int rurka_read[N+1][2];
//initiation of N players
int i;
for(i = 1; i <= N; i++)
{
//tworze lacza
if (pipe(rurka_write[i]) == -1)
printf("wystapil blad przy rurce %d\n", i);
if (pipe(rurka_read[i]) == -1)
printf("wystapil blad przy rurce %d\n", i);
}
for(i = 1; i <= N; i++)
{
switch(pid = fork())
{
case -1:
printf("wystapil blad przy forkowaniu");
case 0:
printf("potomek numer %d\n", i);
if (close(rurka_write[i][1]) == -1)
printf("zle zamykanie");
if (close(rurka_read[i][0]) == -1)
printf("zle zamykanie");
//closing useless descriptors
int j;
for(j = 1; j <= N; j++)
{
if (j != i)
{
close(rurka_read[j][0]);
close(rurka_read[j][1]);
close(rurka_write[j][0]);
close(rurka_write[j][1]);
}
}
char str_N[20];
char str_i[20];
char str_0[20];
char str_1[20];
sprintf(str_N, "%d", N);
sprintf(str_i, "%d", i);
sprintf(str_0, "%d", rurka_write[i][0]);
sprintf(str_1, "%d", rurka_read[i][1]);
printf("%d Executing execl\n", i);
execl("./ucz", str_N, str_i, str_0, str_1, NULL);
printf("execl executed\n");
// execv("./ucz", str_N, str_i, str_0, str_1, NULL);
//exit(0);
default:
//closing useless pipes
if (close(rurka_read[i][1]) == -1)
printf("zle zamykanie rurki do czytania z potomkna\n");
if (close(rurka_write[i][0]) == -1)
printf("zle zamykanie rurki do pisania do potomka\n");
} //end of switch
} //end of for
//if I am in parent, I'm starting the game
if (pid != 0)
// delay(100);
{
printf("PLAY\n");
int l = 1;
while(l > 0)
{
printf("sending to player %d\n", l);
a = fdopen(rurka_write[l][1], "w");
printf("sending: Wake up");
fprintf(a, "Wake up\n");
printf("flushing");
fflush(a);
char k[20];
printf("reading");
read(rurka_read[l][0], k, 20);
l = k;
}
}
}
Besides the fact that you do not end your cases with a break (as noted by strager), the main problem is the statement l = k;. Note that k is a char[20] and, when assigned to a int, you don't assign any of the contents of k to l. Instead l will contain (the value of) the pointer to the array. You will have to do something different here to get the value that is in the array; what exactly depends on that ucz sends back.
After fixing this and making my own ucz, the program seems to work without any problem. Of course, it might also be that there is another problem in your version of ucz.
About ./ucz -- it takes 4 parameters -- 1st -- number of players, 2nd -- player number, 3rd -- number of descriptor to read from parent, 4th -- number of descriptor to write to parent.
Adding exit(0), return(0), break after exec (or in the end of "case: 0") doesn't help.

Resources