Попробовал задачку посложнее сделать, распределенное вычисление суммы массива (для утяжеления расчета перед суммированием применяется произвольная процедура). Блокирующий прием и передача также нормально работают. Получается примерно в три раза быстрее сделать расчет на 4-х ядрах.

## Код:
```
dia@hp:~/oberon/bb-freenix/MPI$ time mpiexec.mpich2 -n 1 ./blackboxc
Process 0 / 1
Total: 655520136.8390013

real   1m26.015s
user   1m25.872s
sys   0m0.020s
dia@hp:~/oberon/bb-freenix/MPI$ time mpiexec.mpich2 -n 2 ./blackboxc
Process 0 / 2
Process 1 / 2
Process 1 sum is 327760068.4224058
Process 0 sum is 327760068.4224058
Total: 655520136.8448116

real   0m43.154s
user   1m26.192s
sys   0m0.008s
dia@hp:~/oberon/bb-freenix/MPI$ time mpiexec.mpich2 -n 3 ./blackboxc
Process 2 / 3
Process 0 / 3
Process 1 / 3
Process 2 sum is 218508460.3361039
Process 0 sum is 218505838.2555565
Process 1 sum is 218505838.2555565
Total: 655520136.847217

real   0m36.934s
user   1m50.220s
sys   0m0.280s
dia@hp:~/oberon/bb-freenix/MPI$ time mpiexec.mpich2 -n 4 ./blackboxc
Process 0 / 4
Process 1 / 4
Process 3 / 4
Process 2 / 4
Process 3 sum is 163880034.2117313
Process 1 sum is 163880034.2117313
Process 2 sum is 163880034.2117313
Process 0 sum is 163880034.2117313
Total: 655520136.8469253

real   0m30.281s
user   1m54.208s
sys   0m0.096s
```


Вот так выглядит код модуля. К сообщению приложил сборку, которую использовал, и наброски заголовочных файлов к MPI.
## Код:
```
MODULE Init;

   IMPORT SYSTEM, Kernel, Log, Math, LinLog, Strings, ObxRandom, Mpi := MpiMpi;

   VAR
      res, myrank, size: INTEGER;
      sizeStr, rankStr: ARRAY 8 OF CHAR;
      status: Mpi.MPI_Status;
      
   PROCEDURE F (a: REAL): REAL;
   VAR i, j: INTEGER; res: REAL;
   BEGIN
      res := 0;
      FOR i := 0 TO 1000 DO
         res := res + Math.Sin(a) + Math.Cos(a * 0.9) / (Math.Sin(a * 0.9) + Math.Cos(a))
      END;
      RETURN res
   END F;

   PROCEDURE SumSin (a: ARRAY OF REAL): REAL;
   CONST
      bal = 4; (* Балланс, количество процессов, до которого нулевой процесс участвует в расчетах (всегда > 1) *)
   VAR
      i, p, bite, rest, shift: INTEGER;  sum, sum_ext: REAL; sumStr: ARRAY 64 OF CHAR;
   BEGIN
      (* Проверяем есть ли необходимость параллелить процесс суммирования *)
      IF (size > 1) & (LEN(a) > 1000) THEN
         (* Разбиваем массив в зависимости от того, участвует нулевой процесс в расчетах или нет *)
         IF size <= bal THEN
            shift := 0;
            bite := LEN(a) DIV size;
            rest := bite + LEN(a) MOD size
         ELSE
            shift := -1;
            bite := LEN(a) DIV (size - 1);
            rest := bite + LEN(a) MOD (size - 1)
         END;
         
         IF myrank = 0 THEN
            (* Отправляем данные остальным процессам *)
            IF size > 2 THEN
               FOR p := 1 TO size - 2 DO
                  res := Mpi.MPI_Send(SYSTEM.ADR(a[bite * (p + shift)]), bite, Mpi.MPI_DOUBLE, p, 1, Mpi.MPI_COMM_WORLD);
               END;
               res := Mpi.MPI_Send(SYSTEM.ADR(a[LEN(a) - rest]), rest, Mpi.MPI_DOUBLE, size - 1, 1, Mpi.MPI_COMM_WORLD)
            ELSE
               res := Mpi.MPI_Send(SYSTEM.ADR(a[bite]), rest, Mpi.MPI_DOUBLE, 1, 1, Mpi.MPI_COMM_WORLD);
            END;
            
            sum := 0;
            IF size <= bal THEN
               FOR i:=0 TO bite - 1 DO
                  sum := sum + F(a[i]) 
               END;
               Strings.RealToString(sum, sumStr);
               Log.String("Process " + rankStr + " sum is " + sumStr + 0AX);
            END;
            
            (* Собираем результаты расчетов *)
            FOR p := 1 TO size - 1 DO
               res := Mpi.MPI_Recv(SYSTEM.ADR(sum_ext), 1, Mpi.MPI_DOUBLE, p, 2, Mpi.MPI_COMM_WORLD, SYSTEM.ADR(status));
               sum := sum + sum_ext
            END

         ELSIF myrank = size - 1 THEN
            (* Вычисления последнего процесса, в случае двух - второго *)
            res := Mpi.MPI_Recv(SYSTEM.ADR(a), rest, Mpi.MPI_DOUBLE, 0, 1, Mpi.MPI_COMM_WORLD, SYSTEM.ADR(status));
            sum := 0;
            FOR i:=0 TO rest - 1 DO
               sum := sum + F(a[i])
            END;
            Strings.RealToString(sum, sumStr);
            Log.String("Process " + rankStr + " sum is " + sumStr + 0AX);
            res := Mpi.MPI_Send(SYSTEM.ADR(sum), 1, Mpi.MPI_DOUBLE, 0, 2, Mpi.MPI_COMM_WORLD)
         ELSE
            (* Вычисления остальных процессов *)
            res := Mpi.MPI_Recv(SYSTEM.ADR(a), bite, Mpi.MPI_DOUBLE, 0, 1, Mpi.MPI_COMM_WORLD, SYSTEM.ADR(status));
            sum := 0;
            FOR i:=0 TO bite - 1 DO
               sum := sum + F(a[i])
            END;
            Strings.RealToString(sum, sumStr);
            Log.String("Process " + rankStr + " sum is " + sumStr + 0AX);
            res := Mpi.MPI_Send(SYSTEM.ADR(sum), 1, Mpi.MPI_DOUBLE, 0, 2, Mpi.MPI_COMM_WORLD)
         END
      ELSE
         (* Суммируем без использования распределенных вычислений *)
         sum := 0;
         FOR i:=0 TO LEN(a) - 1 DO
            sum := sum + F(a[i])
         END
      END;
      RETURN sum
   END SumSin;

   

   PROCEDURE Init*;
   VAR a: ARRAY 10000 OF INTEGER; b: ARRAY 500000 OF REAL;  i, sum: INTEGER; sum2: REAL; sumStr: ARRAY 64 OF CHAR;
   BEGIN
      LinLog.Open;
      res := Mpi.MPI_Init(SYSTEM.ADR(Kernel.bootInfo.argc), SYSTEM.ADR(Kernel.bootInfo.argv));
      res := Mpi.MPI_Comm_size(Mpi.MPI_COMM_WORLD, SYSTEM.ADR(size));
      res := Mpi.MPI_Comm_rank(Mpi.MPI_COMM_WORLD, SYSTEM.ADR(myrank));
      Strings.IntToString(size, sizeStr);
      Strings.IntToString(myrank, rankStr);
      Log.String("Process " + rankStr + " / " + sizeStr + 0AX);
      
      
      
      IF myrank = 0 THEN
         FOR i :=0 TO LEN(b) - 1 DO
            b[i] := 0.987981723;
         END;
      END;
      
      sum2 := SumSin(b);
      
      IF myrank = 0 THEN
         Strings.RealToString(sum2, sumStr);
         Log.String("Total: " + sumStr + 0AX);
      END;
      
      res := Mpi.MPI_Finalize()
   END Init;
   
BEGIN
   Init;
   Kernel.Quit(0)
END Init.
```
