| 1 | /*****************************************
|
|---|
| 2 | * SOURCE: adder_par.c by vsl@udel
|
|---|
| 3 | * The source program is included in FEVS
|
|---|
| 4 | * vsl.cis.udel.edu/fevs
|
|---|
| 5 | * FILE: adder_par.cvl
|
|---|
| 6 | * DESCRIPTION: This a manually translated
|
|---|
| 7 | * CIVL program which is based on "adder_par.c"
|
|---|
| 8 | * This program sums all elements of an array
|
|---|
| 9 | * up.
|
|---|
| 10 | *
|
|---|
| 11 | * AUTHOR: Ziqing Luo
|
|---|
| 12 | * COMMANS: civl verify adder_par.cvl
|
|---|
| 13 | * -inputNPROCSB=5 -inputNB=10
|
|---|
| 14 | * or
|
|---|
| 15 | * make civl
|
|---|
| 16 | *****************************************/
|
|---|
| 17 |
|
|---|
| 18 | #include<civlc.cvh>
|
|---|
| 19 | #include<stdio.h>
|
|---|
| 20 | #include<mpi.h>
|
|---|
| 21 | #include<civl-mpi.cvh>
|
|---|
| 22 | #include<assert.h>
|
|---|
| 23 |
|
|---|
| 24 | $input int NPROCS;
|
|---|
| 25 | $input int NPROCSB;
|
|---|
| 26 | $input int N;
|
|---|
| 27 | $input int NB;
|
|---|
| 28 | $input double a[N];
|
|---|
| 29 | $output double SUM;
|
|---|
| 30 | $assume(0 < N && N < NB);
|
|---|
| 31 | $assume(0 < NPROCS && NPROCS <= NPROCSB);
|
|---|
| 32 | $assume(NPROCS <= N);
|
|---|
| 33 |
|
|---|
| 34 | $scope root = $here;
|
|---|
| 35 | $mpi_gcomm __MPI_COMM_WORLD;
|
|---|
| 36 |
|
|---|
| 37 | void _mpi_process(int place){
|
|---|
| 38 | double sum;
|
|---|
| 39 | double localSum = 0.0;
|
|---|
| 40 | int PID;
|
|---|
| 41 | int nprocs;
|
|---|
| 42 | MPI_Comm MPI_COMM_WORLD;
|
|---|
| 43 | $mpi_sys_status _mpi_status = __UNINIT;
|
|---|
| 44 |
|
|---|
| 45 | $assert(_mpi_status == __UNINIT);
|
|---|
| 46 | double computeGlobalSum() {
|
|---|
| 47 | double result = localSum;
|
|---|
| 48 | double buffer;
|
|---|
| 49 | int i;
|
|---|
| 50 | MPI_Status status;
|
|---|
| 51 |
|
|---|
| 52 | for (i=1; i<nprocs; i++) {
|
|---|
| 53 | MPI_Recv(&buffer, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status);
|
|---|
| 54 | result += buffer;
|
|---|
| 55 | }
|
|---|
| 56 | return result;
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | int _main() {
|
|---|
| 60 |
|
|---|
| 61 | int first;
|
|---|
| 62 | int afterLast;
|
|---|
| 63 | int i;
|
|---|
| 64 |
|
|---|
| 65 | MPI_COMM_WORLD = $mpi_comm_create($here, __MPI_COMM_WORLD, place);
|
|---|
| 66 | $mpi_init();
|
|---|
| 67 | MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
|---|
| 68 | MPI_Comm_rank(MPI_COMM_WORLD, &PID);
|
|---|
| 69 | first = N * PID / nprocs;
|
|---|
| 70 | afterLast = N * (PID + 1) / nprocs;
|
|---|
| 71 |
|
|---|
| 72 | for (i=first; i<afterLast; i++) localSum += a[i];
|
|---|
| 73 | if (PID == 0) {
|
|---|
| 74 | sum = computeGlobalSum();
|
|---|
| 75 | SUM = sum;
|
|---|
| 76 | printf("%lf\n", sum);
|
|---|
| 77 | } else {
|
|---|
| 78 | MPI_Send(&localSum, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
|
|---|
| 79 | }
|
|---|
| 80 | $mpi_finalize();
|
|---|
| 81 | $mpi_comm_destroy(MPI_COMM_WORLD);
|
|---|
| 82 | return 0;
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | _main();
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | void main(){
|
|---|
| 89 | for(int i = 0; i<NPROCS; i++);
|
|---|
| 90 | for(int i = 0; i<N; i++);
|
|---|
| 91 |
|
|---|
| 92 | $proc procs[NPROCS];
|
|---|
| 93 |
|
|---|
| 94 | __MPI_COMM_WORLD = $mpi_gcomm_create(root, NPROCS);
|
|---|
| 95 | for(int i = 0; i<NPROCS; i++)
|
|---|
| 96 | procs[i] = $spawn _mpi_process(i);
|
|---|
| 97 | for(int i = 0; i<NPROCS; i++)
|
|---|
| 98 | $wait(procs[i]);
|
|---|
| 99 | $mpi_gcomm_destroy(__MPI_COMM_WORLD);
|
|---|
| 100 | }
|
|---|