Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > процессы


Автор: IgnatM 1.5.2011, 16:27
нужно написать программу, которая вычисляет значение интеграла функции 4/(1+Х^2) на интервале значений 0..1, методом трапеций, где каждый элемент суммы, вычисляется в отдельном процессе....

вот мой код, но в чем - то проблема - процессор перегружается и конечное значение интеграла выводиться несколько раз, я так понимаю промежуточные..Помогите пожалйста
Код

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

double func (double x) {
    return 4/(1 + x*x);
}
int
fatal (char *s)
{
  perror (s);
  exit (1);
}

int main (void) {

    int i,N,status,exit_status;
    double a,b,x_f,x_d,h,sum,new_add;
    pid_t pid,p;

    a = 0;
    b = 1;
    N = 20;
    sum = 0.0;
    h = (b - a) / N;
    x_d = a;
    for (i = 0; i < N; i++){
        if ((pid = fork ()) < 0)
             fatal ("Îøèáêà âûçîâà fork ");
        
        if (pid == 0) {
            printf ("Ïîòîìîê %d ïàóçà...\n", getpid ());
            x_f = a + i*h;
            new_add = func(x_d) + func(x_f);
            x_d = x_f;
            //sleep(4);
                                    
        }
        if (waitpid (pid, &status, WNOHANG) == 0)
         {
               perror ("Phter ");
               
         }
        if (WIFEXITED (status)) {
               exit_status = WEXITSTATUS (status);
              printf ("Ñòàòóñ çàâåðøåíèÿ %d ðàâåí %d\n", pid, exit_status);
                                 
        }
        sum = sum + new_add;
        
    }
    sum = h/2 *sum;
    printf ("\nIntegral = %2.2f\n",sum);
    
    return 0;
}




Автор: svlary 3.5.2011, 05:12
Цитата(IgnatM @  1.5.2011,  16:27 Найти цитируемый пост)
new_add = func(x_d) + func(x_f);

  Т.е. Вы вычисляете значение дельты (new_add) в дочернем процессе, а присуммируете его 
Код

sum = sum + new_add;

  в родительском ? smile

Автор: IgnatM 3.5.2011, 10:18
Да, так я хотел сделать, но не уверен, что суммирование происходит в родительском.

Автор: svlary 3.5.2011, 11:07
Цитата(IgnatM @  3.5.2011,  10:18 Найти цитируемый пост)
но не уверен

  Так делать нельзя. Просто потому, что родительский и дочерний процесс работают в разных и никак не связанных областях памяти. Дочерний процесс, в  момент создания. получает КОПИЮ области памяти родительского. Но дальше их дорожки расходятся и пытаться использовать значение переменной дочернего процесса в родительском, то же самое, что использовать подсказки из загробного мира в делах житейских... smile  Короче, искренний совет - читайте доку !

Автор: null56 3.5.2011, 16:16
IgnatM, извиняюсь за любопытство, хоть я и не любопытный, это принципиальная задача делать параллельно эти вычисления?

если приципиально, то через процессы, почитай:
http://linux.die.net/man/2/shmget
http://linux.die.net/man/3/sem_init

через потоки отталкивайся от (pthread)
http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread.h.html]=http://pubs.opengroup.org/onlinepubs/007908799/xsh/pthread.h.html

Автор: IgnatM 3.5.2011, 17:09
Здесь это не принципиально, нигде использоваться это больше не будет, но все же нужно сделать(( 

Автор: null56 3.5.2011, 18:37
ну если ты принципиально не хочешь использовать потоки, то придется подумать над тем, как передать данные от одного процесса другому... один способ я тебе упомянул выше, но можешь еще воспользоваться неименованными каналами
почитай man pipe
то есть код изменится примерно так
Код

int ipc_pipe[2];
if (pipe(ipc_pipe) == -1) 
{
//... ошибка
}
    for (i = 0; i < N; i++){
        if ((pid = fork ()) < 0)
             fatal ("Îøèáêà âûçîâà fork ");
     
// дочерний процесс   
        if (pid == 0) {
            printf ("Ïîòîìîê %d ïàóçà...\n", getpid ());
            x_f = a + i*h;
            new_add = func(x_d) + func(x_f);
            x_d = x_f;
            //sleep(4);
close(ipc_pipe[0]);
write(icp_pipe[1], &new_add, sizeof(new_add));
close(icp_pipe[1]);
        }

// родительский процесс
close(ipc_pipe[1]);
read(icp_pipe[0], &new_add, sizeof(new_add));
close(icp_pipe[0]);
        if (waitpid (pid, &status, WNOHANG) == 0)
         {
               perror ("Phter ");
               
         }
        if (WIFEXITED (status)) {
               exit_status = WEXITSTATUS (status);
              printf ("Ñòàòóñ çàâåðøåíèÿ %d ðàâåí %d\n", pid, exit_status);
                                 
        }
        sum = sum + new_add;
        
    }

я не проверял, то что набросал, если пахать не будет, почитай man pipe, снизу страницу помощи, есть пример использонвания
http://www.opennet.ru/man.shtml?topic=pipe&category=2&russian=2

Автор: MAKCim 3.5.2011, 20:48
еще можно mmap с MAP_SHARED перед форком

Автор: IgnatM 8.5.2011, 19:19
Сделал с помощью pipe. Вот код:
Код

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <assert.h>

double func (double x) {
    return 4/(1 + x*x);
}
int
fatal (char *s)
{
  perror (s);
  exit (1);
}

double add(double x_d,double x_f) {
    return (func(x_d) + func(x_f));
}

int main (void) {
    int i,N,status,exit_status;
    double a,b,x_f,x_d,h,sum,new_add;
    pid_t pid,p;
    int ipc_pipe[2];

    if (pipe(ipc_pipe) == -1) {
         perror("pipe");
         exit(EXIT_FAILURE);
     }
    a = 0; b = 1; sum = 0.0;
    N = 20;
    h = (b - a) / N;
    x_d = a;
    for (i = 0; i < N; i++){
        x_f = x_d + h;
        pid = fork();
        if(pid == 0) {
            new_add = add(x_d,x_f);
            write(ipc_pipe[1], &new_add, sizeof(new_add));
            return ;
        }
        else if (pid == -1){
            printf("Error for");
            
        }
        else{
            wait((int *) 0);        
            read(ipc_pipe[0], &new_add, sizeof(new_add));
            sum = sum + new_add;            
            x_d = x_f;
            //printf("New add = %2.2f\n",new_add);
        }
    }
    close(ipc_pipe[1]);    
    close(ipc_pipe[0]);    
    sum = h/2 *sum;
    printf ("\nIntegral = %2.2f\n",sum);
        
    return 0;
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)