C - вилка - проблема ожидания - PullRequest
2 голосов
/ 09 июля 2010

Я написал этот код:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/shm.h>

#define   N  512

void  chunk0(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it);
void  chunk1(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it);
void  chunk2(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it);
void  chunk3(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it);
double get_time(void);

void  main(void)
{
    int i,j,k,iterations=0;
    int plc=N/4;
    unsigned int *a=(unsigned int *)malloc(N*N*(sizeof(unsigned int)));
    unsigned int *b=(unsigned int *)malloc(N*N*(sizeof(unsigned int)));
    unsigned int shmsz=N*N*(sizeof(unsigned int));
    pid_t  pid;

    srand ( time(NULL) );
    double start=get_time();

    int shmid;
    if ((shmid = shmget(IPC_PRIVATE, shmsz, IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }
    //Now we attach the segment to our data space.
    char *shm;
    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }   
    unsigned int *s = (unsigned int *) shm;

    for(iterations=0;iterations<1000;iterations++){
        printf("Iteration #%d\n",iterations+1);
        for(i=0;i<N;i++){
            for(j=0;j<N;j++){
                *(a+(i*N+j))=(rand()%1001);
                *(b+(i*N+j))=(rand()%1001);;
                *(s+(i*N+j))=0;
            }
        }

        pid = fork();
        if (pid == 0) {
             chunk0(s,a,b,plc,iterations);
             break;
        }else {
            pid = fork();
            if (pid == 0){ 
                 chunk1(s,a,b,plc,iterations);
                 break;
            }else {
                pid = fork();
                if (pid == 0){ 
                     chunk2(s,a,b,plc,iterations);
                     break;
                }else {
                    chunk3(s,a,b,plc,iterations);
                    wait(NULL);
                }
            }
        }
        wait(NULL);
    }

    double end=get_time();
    double diff=end-start;
    printf("\n Time for run this code is: %lf seconds \n",diff);

}

void  chunk0(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it)
{
    int i,j,k;

    for(i=0;i<MID;i++){
        for(j=0;j<N;j++){
            for(k=0;k<N;k++){
                *(s+(i*N+j))=*(s+(i*N+j))+(*(a+(i*N+k)))*(*(b+(k*N+j)));
            }   
        }
    }
    printf("\tChild process 0 (Iteration %d) is done ***\n",it);
    exit(0);
}
void  chunk1(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it)
{
    int i,j,k;

    for(i=MID;i<MID*2;i++){
        for(j=0;j<N;j++){
            for(k=0;k<N;k++){
                *(s+(i*N+j))=*(s+(i*N+j))+(*(a+(i*N+k)))*(*(b+(k*N+j)));
            }
        }
    }
     printf("\tChild process 1 (Iteration %d) is done ***\n",it);
     exit(0);
}
void  chunk2(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it)
{
    int i,j,k;

    for(i=MID*2;i<MID*3;i++){
        for(j=0;j<N;j++){
            for(k=0;k<N;k++){
                *(s+(i*N+j))=*(s+(i*N+j))+(*(a+(i*N+k)))*(*(b+(k*N+j)));
            }
        }
    }

     printf("\tChild process 2 (Iteration %d) is done ***\n",it);
     exit(0);
}
void  chunk3(unsigned int *s, unsigned int *a, unsigned int *b, int MID,int it)
{
     int i,j,k;

    for(i=MID*3;i<N;i++){
        for(j=0;j<N;j++){
            for(k=0;k<N;k++){
                *(s+(i*N+j))=*(s+(i*N+j))+(*(a+(i*N+k)))*(*(b+(k*N+j)));
            }
        }
    }

     printf("\tChild process 3 (Iteration %d) is done ***\n",it);
//     exit(0);
}

double get_time(void){
    struct timeval stime;
    gettimeofday (&stime, (struct timezone*)0);
    return (stime.tv_sec+((double)stime.tv_usec)/1000000);
}  

Программа не ждет завершения одной итерации и запускает следующую итерацию!
Посмотрите на результаты:

Iteration #1
    Child process 0 (Iteration 0) is done ***
    Child process 3 (Iteration 0) is done ***
    Child process 1 (Iteration 0) is done ***
Iteration #2
    Child process 2 (Iteration 0) is done ***
    Child process 0 (Iteration 1) is done ***
    Child process 1 (Iteration 1) is done ***
    Child process 3 (Iteration 1) is done ***
Iteration #3
    Child process 2 (Iteration 1) is done ***
    Child process 0 (Iteration 2) is done ***
    Child process 3 (Iteration 2) is done ***
Iteration #4
    Child process 1 (Iteration 2) is done ***
    Child process 2 (Iteration 2) is done ***
    Child process 1 (Iteration 3) is done ***
    Child process 3 (Iteration 3) is done ***
Iteration #5
    Child process 0 (Iteration 3) is done ***
    Child process 2 (Iteration 3) is done ***
    Child process 0 (Iteration 4) is done ***
    Child process 1 (Iteration 4) is done ***
    Child process 2 (Iteration 4) is done ***
    Child process 3 (Iteration 4) is done ***
Iteration #6
    Child process 1 (Iteration 5) is done ***
    Child process 0 (Iteration 5) is done ***
    Child process 2 (Iteration 5) is done ***
    Child process 3 (Iteration 5) is done ***
Iteration #7
    Child process 0 (Iteration 6) is done ***
    Child process 1 (Iteration 6) is done ***
    Child process 2 (Iteration 6) is done ***
    Child process 3 (Iteration 6) is done ***

Как насчетэто?
Я использовал wait (NULL), но ...

Ответы [ 2 ]

7 голосов
/ 09 июля 2010

wait() будет ожидать только выхода одного дочернего процесса. Вы хотите подождать, пока они все не вышли. Я думаю, вам просто нужно назвать это 3 раза подряд ...

1 голос
/ 09 июля 2010

Вы неправильно ожидаете созданные вами дочерние процессы. Вы должны сделать это так:

pid = fork();
if (pid == 0) {
    chunk0(s,a,b,plc,iterations);
    break;
}else {
    pid = fork();
    if (pid == 0){ 
        chunk1(s,a,b,plc,iterations);
        break;
    }else {
        pid = fork();
        if (pid == 0){ 
            chunk2(s,a,b,plc,iterations);
            break;
        }else {
            chunk3(s,a,b,plc,iterations);
            wait(NULL);
        }
        wait(NULL);
    }
    wait(NULL);
}

Это выглядит довольно ужасно, и вам следует переосмыслить логику вашей программы, чтобы сделать ее более читабельной. Кроме того, не забудьте правильно очистить ресурсы от дочерних процессов перед выходом (см. shmdt ).

Еще одна вещь, которую следует учитывать, - это использовать shm_open и shm_unlink .

...