Thread: simple and short fork-join parallelization

  1. #1
    Registered User
    Join Date
    Jul 2005
    Posts
    6

    simple and short fork-join parallelization

    Hello,
    after reading many tutorials on how to start a new process using fork() I'm still having some dificulty understanding it. What I would like to achieve is, for my own understanding, a simple code that starts two DIFFERENT calculations as separate processes at the SAME time and then when both are finished, a third calculation adds computed values of both processes. It is very important that both processes start at the same time and run in parallel to each other and if, for example, one of both processes finishes first, it STILL waits for second process to finish and then both processes are terminated and values from their calculations are added together. I was thinking of something like this:

    Code:
    a=1+1   ..this is computed in one process
    
    b=2+2  ..this is computed in second process which runs PARALLEL to the first one
                 and is started as separate process at the SAME time as the first process
    
    ..then, after both processes are finished:
    
    c=a+b   ..the value of c must then be ofcourse 6. Also, if for example process
                 a=1+1 finishes first (or does so process b=2+2), it waits for the other to 
                 finish so they also terminate at the same time before c=a+b is 
                 calculated.
    ..now the code I tried is:

    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main()
    {
    
    int pid;
    float a, b, c;
    
    pid = fork();
    
    if (pid == 0) 
    a=1+1;
    
    else wait();
    b=2+2;
    
    c=a+b;
    printf("c=%f\n", c);
    
    return 0;
    
    }
    ..and the output I got is:

    Code:
    c=6.000000
    c=4.000000
    Now I'm not sure if this is correct? It does display c=6 but then also c=4..
    Did both processes start at the same time in the above code (did they run in parallel)?? Can someone confirm this, or better, can maby someone who has good understanding of fork-join processes post the minimal lenght code which would be CORRECT solution for the given problem at the beginning?

    Also, is it possible to start more than two processes at once - let's say that for the above problem there is a third calculation d=3+3, so that we would have 3 processes running at the same time and when they are finished, c is computed as c=a+b+d ? What would the code look like for 3 parallel processes?

    Thank you for any suggestions and help

    regards

    c.
    Last edited by cole01527; 07-02-2005 at 05:24 PM.

  2. #2
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    When you spawn a new process, the new child process receives a copy of the variables (with their values) declared by parent. When you are assigning 2+2 values to 'a'. You are assigning it to child process's copy of variable 'a' which is not the same as variable 'a' which you are using in parent process to add with 'b'.

    Since you have not initialised the variables a,b and c, they may hold any random value. Check this program its same as yours with little modifications.

    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    
    
    
    float a=0.0;
    float b=0.0;
    float c=0.0;
    
    int main()
    {
    
    float a=0.0;
    float b=0.0;
    float c=0.0;
    
    pid_t pid;
    pid_t cpid;
    int status;
    
    
    pid = fork();
    
    if (pid == 0) 
    {
    	a=1+1;
    	printf("a: (in Proc)= %.2f\n",a);
    	sleep(5);
    	exit(0);
    } else {
    	if ((cpid=wait(&status)) == pid)
    	{
    		printf("Child %d returned\n",pid);
    	}
    	b=2+2;
    	printf("a: (in Parent)=%.2f\n", a);
    	printf("b=%.2f\n", b);
    	c=a+b;
    	printf("c=%.2f\n", c);
    
    }
    
    
    return 0;
    
    }
    Following is the program output.

    [root@linux-outside snoopy]# ./proc4
    a: (in Proc)= 2.00
    Child 18799 returned
    a: (in Parent)=0.00
    b=4.00
    c=4.00
    [root@linux-outside snoopy]#
    If you want a variable to be shared (not copied as above) and updated by multiple processes. You need to acquire a shared memory and declare your variable in it. Variables declared using shared memory are not copied to child process. There is only one copy of it and every spawnd process operates on this single copy of the variable. You might wanna consider implementing semaphores to protect concurrent updates on these shared variables by multiple processes.

    HTH,

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    Here is your code modified to show the use of shared memory.

    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    
    
    float *a;
    float *b;
    float *c;
    
    int main()
    {
    
    pid_t pid;
    pid_t cpid;
    int status;
    int shmid;
    float *shm_ptr;
    key_t key=1234;
    
    shmid=shmget(key,3*sizeof(float),0666|IPC_CREAT);
    
    if (shmid < 0)
    {
    	perror("shmget");
    	exit(1);
    }
    
    shm_ptr=(float *)shmat(shmid,(void *)0,0);
    
    if (shm_ptr == (float *)(-1))
    {
    	perror("shmat:shm_ptr");
    	exit(1);
    }
    
    a=shm_ptr;
    b=(shm_ptr+1);
    c=(shm_ptr+2);
    
    pid = fork();
    
    if (pid == 0) 
    {
    	*a=1+1;
    	printf("a: (in Proc)= %.2f\n",*a);
    	sleep(2);
    	exit(0);
    } else {
    	if ((cpid=wait(&status)) == pid)
    	{
    		printf("Child %d returned\n",pid);
    	}
    	*b=2+2;
    	printf("a: (in Parent)=%.2f\n", *a);
    	printf("b=%.2f\n", *b);
    	*c=*a+*b;
    	printf("c=%.2f\n", *c);
    
    }
    
    
    return 0;
    
    }
    Program Output:

    [root@linux-outside snoopy]# ./proc4
    a: (in Proc)= 2.00
    Child 19150 returned
    a: (in Parent)=2.00
    b=4.00
    c=6.00

  4. #4
    Registered User
    Join Date
    Jul 2005
    Posts
    6
    thanks alot mkhambal.

    If I want to add more parallel processes to the above code, but again I'm not sure if it's correct - I now tried a third calculation d=3+3

    Code:
    all processes must be executed at the same time:
    
    a=1+1      first parallel process
    b=2+2     second parallel process
    d=3+3     third parallel process
    
    ..when they finish:
    
    c=a+b+d=12
    ..now this is the code I tried, but can anyone confirm if it's correct (if with this code all three processes are running at the same time?) - here:

    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    
    
    float *a;
    float *b;
    float *c;
    float *d;
    
    int main()
    {
    
    pid_t pid;
    pid_t cpid;
    int status;
    int shmid;
    float *shm_ptr;
    key_t key=1234;
    
    shmid=shmget(key,3*sizeof(float),0666|IPC_CREAT);
    
    if (shmid < 0)
    {
    	perror("shmget");
    	exit(1);
    }
    
    shm_ptr=(float *)shmat(shmid,(void *)0,0);
    
    if (shm_ptr == (float *)(-1))
    {
    	perror("shmat:shm_ptr");
    	exit(1);
    }
    
    a=shm_ptr;
    b=(shm_ptr+1);
    d=(shm_ptr+2);
    c=(shm_ptr+3);
    
    pid = fork();
    
    if (pid == 0) 
    {
    	*a=1+1;
    	printf("a: (in Proc)= %.2f\n",*a);
    	sleep(2);
    	exit(0);
    } 
    
    if (pid == 0) 
    {
    	*d=3+3;
    	printf("a: (in Proc)= %.2f\n",*d);
    	sleep(2);
    	exit(0);
    }
    
    else {
    	if ((cpid=wait(&status)) == pid)
    	{
    		printf("Child %d returned\n",pid);
    	}
    	*b=2+2;
    	printf("a: (in Parent)=%.2f\n", *a);
    	printf("b=%.2f\n", *b);
    	*c=*a+*d+*b;
    	printf("c=%.2f\n", *c);
    
    }
    
    
    return 0;
    
    }
    The result I got is:

    Code:
    a: (in Proc)= 2.00
    Child 2694 returned
    a: (in Parent)=2.00
    b=4.00
    c=12.00

    So, is this correct way to do it for 3 different processes executed at the same time? Using that analogy, if I want to add more parallel processes, do I just:

    Code:
     if (pid == 0) 
    {
    	first process
    } 
    
    if (pid == 0) 
    {
    	second process
    }
    
    if (pid == 0) 
    {
    	third process
    } 
    
    if (pid == 0) 
    {
    	fourth process
    }
    
    ..and so on..
    Is this the shortest and simplest way to do it and to remember?

    I know this may be very "primitive" parallelization method but I'm just looking for the simplest way to remember..

    thanks

    c.

  5. #5
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    Processes run in parallel but not necessarily concurrently. OS's schedular decides how each process is scheduled to receive CPU cycles.

    As far as your code goes, you need to use fork() everytime you need to spwan or create a new process. Following is the correct code for 3 variables updated in 3 different process and their results being updated in the parent process.

    Code:
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    
    float *a;
    float *b;
    float *c;
    float *d;
    
    int main()
    {
    
    pid_t pid,pid1,pid2;
    pid_t cpid,cpid1,cpid2;
    int status;
    int shmid;
    float *shm_ptr;
    key_t key=12345;
    
    shmid=shmget(key,4*sizeof(float),0666|IPC_CREAT);
    
    if (shmid < 0)
    {
    	perror("shmget");
    	exit(1);
    }
    
    shm_ptr=(float *)shmat(shmid,(void *)0,0);
    
    if (shm_ptr == (float *)(-1))
    {
    	perror("shmat:shm_ptr");
    	exit(1);
    }
    
    a=shm_ptr;
    b=(shm_ptr+1);
    c=(shm_ptr+2);
    d=(shm_ptr+3);
    
    
    if ((pid = fork()) == 0) 
    {
    	*a=1+1;
    	printf("a: (in Proc)= %.2f\n",*a);
    	sleep(2);
    	exit(0);
    } else if ((pid1=fork()) == 0)
    {
    	*b=3+3;
    	printf("b: (in Proc)= %.2f\n",*b);
    	sleep(2);
    	exit(0);
    } else if ((pid2=fork()) == 0)
    {
    	*c=4+4;
    	printf("c: (in Proc)= %.2f\n",*c);
    	sleep(2);
    	exit(0);
    } else {	
    	
    	if ((cpid=wait(&status)) == pid)
    	{
    		printf("Child %d returned\n",pid);
    	}
    	if ((cpid1=wait(&status)) == pid1)
    	{
    		printf("Child %d returned\n",pid1);
    	}
    	if ((cpid2=wait(&status)) == pid2)
    	{
    		printf("Child %d returned\n",pid2);
    	}
    	
    	printf("a: (in Parent)=%.2f\n", *a);
    	printf("b: (in Parent)=%.2f\n", *b);
    	printf("c: (in Parent)=%.2f\n", *c);
    
    	*d=*a+*b+*c;
    	printf("d=%.2f\n", *d);
    
    }
    
    if ((shmdt(shm_ptr)) == -1)
    {
    	perror("shmdt");
    } else {
    	if ((shmctl(shmid, IPC_RMID, NULL)) == -1)
    	{
    		perror("shmctl");
    	}
    }
    
    return 0;
    
    }
    Last edited by nkhambal; 07-04-2005 at 01:56 AM.

  6. #6
    Registered User
    Join Date
    Jul 2005
    Posts
    6
    thanks

    I understand now.

    regards

    c.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. int and unsignd short
    By a0161 in forum C Programming
    Replies: 2
    Last Post: 11-11-2008, 04:14 AM
  2. A Simple Compiler/Linker
    By SMurf in forum C Programming
    Replies: 9
    Last Post: 02-17-2005, 03:53 PM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  4. Simple Short Class Question
    By Travis Dane in forum C++ Programming
    Replies: 2
    Last Post: 12-24-2002, 07:12 PM