Для каждого процесса нунжно создать файл-шаблон. Имя такого файла совпадает с именем процесса и имеет расширение frm (можно воспользоваться файлом Process.frm). В нашем случае имеем три файла: Manager.frm, Worker.frm и Summer.frm. В каждом файле есть процедура, имя которой заканчивается на Body. Внутри нее записывается тело процесса.
10 PROCEDURE ManagerBody;
11 VAR
12 Task : RECORD N:cardinal; a,b:real; END;
13 i,WrkId : cardinal;
14 CONST
15 N : cardinal = 10;
16 BEGIN
17 exportNumIter[0].Send (N, SizeOf(N));
18 Task.N := 10*N;
19 Task.b := 0;
20 FOR i := 1 TO N DO BEGIN
21 Task.a := Task.b;
22 Task.b := i * 1.0 / N;
23 importDemandList.Receive (WrkId, SizeOf(WrkId));
24 exportWorker[WrkId].Send (Task, SizeOf(Task));
25 END;
26 Task.N := 0;
27 FOR i := 1 TO exportWorker.NChannels DO
28 exportWorker[i-1].Send (Task, SizeOf(Task));
29 END;
Файл Manager.frm : тело процесса Manager
Переменная Task описывает задание для рабочего процесса: a,b - границы, N - число интервалов. Константа N, описанная в строке 15, равна числу разбиений отрезка [0;1].
В начале работы посылаем процессу Summer число разбиений N (строка 17) . В строке 23 ждем запроса от одного из рабочих процессов. Запрос представляет собой идентификатор запрашивающего процесса. Получив запрос, отсылаем очередное задание соответствующему рабочему (строка 24).
После того, как задания распределены, нужно сообщить об этом всем рабочим процессам. Для этого служат строки 26-28: по всем каналам порта exportWorker посылаем задание с нулевым числом интервалов - сигнал о завершении работы.
30 PROCEDURE WorkerBody;
31 VAR
32 Task : RECORD N:word; a,b:real; END;
33 S : real;
34 i : word;
35 FUNCTION f(x:real):real;
36 BEGIN
37 Result := 4 / (1 + x*x);
38 END;
39 BEGIN
40 exportDemand[0].Send (FloLib.CopyNumber, SizeOf(cardinal));
41 WHILE (true) DO WITH Task DO BEGIN
42 importArg.Receive (Task, SizeOf(Task));
43 IF (Task.N = 0) THEN EXIT;
44 h := (b-a)/N;
45 S := 0;
46 FOR i := 1 TO N DO
47 S := S + f(a+(i-0.5)*h);
48 S := h*S;
49 exportPartSum[0].Send (S, SizeOf(S));
50 exportDemand[0].Send (FloLib.CopyNumber,SizeOf(cardinal));
51 END;
52 END;
Файл Worker.frm : тело процесса Worker
Бесконечный цикл 41-51 обеспечивает работу процесса до получения сигнала завершения от распределителя работ Manager.
В строке 42 ждем очередное задание Task. Если число интервалов в задании равно 0, то завершаем работу. В противном случае вычисляем частичную сумму на интервале (Task.a; Task.b) и отсылаем ее суммирующему процессу (строки 44-49). В строке 50 обращаемся к распределителю работ за очередным заданием.
53 PROCEDURE SummerBody;
54 VAR
55 N, i : cardinal;
56 F : TextFile;
57 TotalSum, S : real;
58 BEGIN
59 importNumIter.Receive (N, SizeOf(N));
60 TotalSum := 0;
61 FOR i := 1 TO N DO BEGIN
62 importPartSum.Receive (S, SizeOf(S));
63 TotalSum := TotalSum + S;
64 END;
65 AssignFile (F, ‘Pi.result’);
66 Rewrite (F);
67 WriteLn (F, ‘Pi = ’, TotalSum);
68 CloseFile (F);
69 END;
Файл Summer.frm : тело процесса Summer
В строках 61-64 собираются частичные суммы от всех рабочих процессов и суммируются в переменной TotalSum. Число частичных сумм записываем в переменну N из порта importNumIter (строка 59).
Дата: 2019-07-30, просмотров: 227.