source: CIVL/examples/backend/mpiSumarray.cvl@ 978afe7

main test-branch
Last change on this file since 978afe7 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 23.6 KB
RevLine 
[7cdceea]1
[7d856cc]2//======================= int_div.cvl ======================
[39c2026]3$system[civlc] void $assert(_Bool expr, ...);
[7cdceea]4$system[int_div] int $remainder(int x, int y);
5$system[int_div] int $quotient(int x, int y);
[f65e51c]6int $int_div(int numerator, int denominator) {
[7d856cc]7 $assert(denominator != 0, "Possible division by zero");
8 if (numerator == 0)
9 return 0;
[f65e51c]10 if (numerator >= 0) {
[7cdceea]11 if (denominator >= 0) {
12 int $sef$0 = $quotient(numerator, denominator);
13 return $sef$0;
14 }
15 else {
16 int $sef$1 = $quotient(numerator, -denominator);
17 return -$sef$1;
18 }
[7d856cc]19 }
[f65e51c]20 else {
[7cdceea]21 if (denominator >= 0) {
22 int $sef$2 = $quotient(-numerator, denominator);
23 return -$sef$2;
24 }
25 else {
26 int $sef$3 = $quotient(-numerator, -denominator);
27 return $sef$3;
28 }
29 }
30}
31//=================== unsigned_arith.cvl ===================
32int $signed_to_unsigned(int x, int bound) {
33 if (x >= 0) {
34 if (x < bound)
35 return x;
36 else {
37 int $sef$9 = $remainder(x, bound);
38 return $sef$9;
39 }
40 }
41 else {
42 if ((-x) <= bound)
43 return bound + x;
44 else {
45 int $sef$10 = $remainder(-x, bound);
46 return bound - $sef$10;
47 }
[7d856cc]48 }
49}
[f65e51c]50//======================= sum_array.c ======================
51$input int _civl_argc;
52$system[civlc] void $assume(_Bool expression);
53$assume(0 < _civl_argc);
54$input char _civl_argv[_civl_argc][];
[7d856cc]55//======================== civlc.cvh =======================
56typedef struct $scope $scope;
[6b88ea3]57/*@ depends_on \nothing;
[c3bddc1]58 @ executes_when $true;
[6b88ea3]59 @*/
60$system[civlc] void* $malloc($scope s, int size);
[7cdceea]61typedef unsigned long size_t;
[f65e51c]62typedef struct $proc $proc;
[7cdceea]63typedef struct $state $state;
[7d856cc]64/*@ depends_on \nothing;
[c3bddc1]65 @ executes_when $true;
[7d856cc]66 @*/
[39c2026]67$system[civlc] void $assert(_Bool expr, ...);
[7d856cc]68/*@ depends_on \nothing;
[c3bddc1]69 @ executes_when $true;
[7d856cc]70 @*/
[39c2026]71$system[civlc] void $assume(_Bool expr);
[3c8cc6c]72
[7cdceea]73/*@ depends_on \access(p);
[c3bddc1]74 @ executes_when $true;
[fccb5a6]75 @*/
76$system[civlc] void $free(void* p);
[7cdceea]77//========================== mpi.h =========================
78typedef enum MPI_Datatype{
79 MPI_CHAR=0,
80 MPI_CHARACTER=1,
81 MPI_SIGNED_CHAR,
82 MPI_UNSIGNED_CHAR,
83 MPI_BYTE=2,
84 MPI_WCHAR,
85 MPI_SHORT=3,
86 MPI_UNSIGNED_SHORT,
87 MPI_INT=4,
88 MPI_INT16_T,
89 MPI_INT32_T,
90 MPI_INT64_T,
91 MPI_INT8_T,
92 MPI_INTEGER,
93 MPI_INTEGER1,
94 MPI_INTEGER16,
95 MPI_INTEGER2,
96 MPI_INTEGER4,
97 MPI_INTEGER8,
98 MPI_UNSIGNED,
99 MPI_LONG=5,
100 MPI_UNSIGNED_LONG,
101 MPI_FLOAT=9,
102 MPI_DOUBLE=10,
103 MPI_LONG_DOUBLE=11,
104 MPI_LONG_LONG_INT=6,
105 MPI_UNSIGNED_LONG_LONG=7,
106 MPI_LONG_LONG=8,
107 MPI_PACKED,
108 MPI_LB,
109 MPI_UB,
110 MPI_UINT16_T,
111 MPI_UINT32_T,
112 MPI_UINT64_T,
113 MPI_UINT8_T,
114 MPI_FLOAT_INT,
115 MPI_DOUBLE_INT,
116 MPI_LONG_INT,
117 MPI_SHORT_INT,
118 MPI_2INT=12,
119 MPI_LONG_DOUBLE_INT,
120 MPI_AINT,
121 MPI_OFFSET,
122 MPI_2DOUBLE_PRECISION,
123 MPI_2INTEGER,
124 MPI_2REAL,
125 MPI_C_BOOL,
126 MPI_C_COMPLEX,
127 MPI_C_DOUBLE_COMPLEX,
128 MPI_C_FLOAT_COMPLEX,
129 MPI_C_LONG_DOUBLE_COMPLEX,
130 MPI_COMPLEX,
131 MPI_COMPLEX16,
132 MPI_COMPLEX32,
133 MPI_COMPLEX4,
134 MPI_COMPLEX8,
135 MPI_REAL,
136 MPI_REAL16,
137 MPI_REAL2,
138 MPI_REAL4,
139 MPI_REAL8
140} MPI_Datatype;
[f65e51c]141//======================= sum_array.c ======================
142$input long NB = 20;
143$input long N;
144$assume((0 < N) && (N <= NB));
[fccb5a6]145//========================= seq.cvh ========================
[7cdceea]146/*@ depends_on \access(array);
[c3bddc1]147 @ executes_when $true;
148 @*/
149$system[seq] int $seq_length(void* array);
[7cdceea]150/*@ depends_on \access(array, value);
[c3bddc1]151 @ executes_when $true;
152 @*/
[fccb5a6]153$system[seq] void $seq_init(void* array, int count, void* value);
[7cdceea]154/*@ depends_on \access(array, values);
[c3bddc1]155 @ executes_when $true;
156 @*/
157$system[seq] void $seq_insert(void* array, int index, void* values, int count);
[7cdceea]158/*@ depends_on \access(array, values);
[c3bddc1]159 @*/
160$atomic_f void $seq_append(void* array, void* values, int count);
[7d856cc]161//======================= bundle.cvh =======================
[53d9ac1]162typedef struct _bundle $bundle;
[7cdceea]163/*@ depends_on \access(ptr);
[c3bddc1]164 @ executes_when $true;
[7d856cc]165 @*/
[f010003]166$system[bundle] $bundle $bundle_pack(const void* ptr, int size);
[7cdceea]167/*@ depends_on \access(ptr);
[c3bddc1]168 @ executes_when $true;
169 @*/
[39c2026]170$system[bundle] void $bundle_unpack($bundle bundle, void* ptr);
[7d856cc]171//===================== concurrency.cvh ====================
[c3bddc1]172typedef struct _gbarrier* $gbarrier;
173typedef struct _barrier* $barrier;
174/*@ depends_on \nothing;
[dba07d0]175 @ assigns \nothing;
[fccb5a6]176 @ reads \nothing;
[7d856cc]177 @*/
[fccb5a6]178$atomic_f $gbarrier $gbarrier_create($scope scope, int size);
[7cdceea]179/*@ depends_on \access(gbarrier);
[fccb5a6]180 @ reads \nothing;
181 @ assigns gbarrier;
[7d856cc]182 @*/
[fccb5a6]183$atomic_f void $gbarrier_destroy($gbarrier gbarrier);
[7d856cc]184/*@ depends_on \nothing;
[fccb5a6]185 @ assigns gbarrier;
186 @ reads gbarrier;
[7d856cc]187 @*/
[fccb5a6]188$atomic_f $barrier $barrier_create($scope scope, $gbarrier gbarrier, int place);
[7cdceea]189/*@ depends_on \access(barrier);
[fccb5a6]190 @ assigns barrier;
191 @ reads \nothing;
[7d856cc]192 @*/
[fccb5a6]193$atomic_f void $barrier_destroy($barrier barrier);
[7d856cc]194//======================== comm.cvh ========================
[c3bddc1]195typedef struct _message{
[f65e51c]196 int source;
197 int dest;
198 int tag;
199 $bundle data;
200 int size;
[7d856cc]201} $message;
[c3bddc1]202typedef struct _queue $queue;
203typedef struct _gcomm* $gcomm;
204typedef struct _comm* $comm;
[7cdceea]205/*@ depends_on \access(data);
[7d856cc]206 @ executes_when $true;
207 @*/
208$atomic_f $message $message_pack(int source, int dest, int tag, void* data, int size);
[7cdceea]209/*@ depends_on \nothing;
[7d856cc]210 @ executes_when $true;
211 @*/
212$atomic_f int $message_source($message message);
[7cdceea]213/*@ depends_on \nothing;
[7d856cc]214 @ executes_when $true;
215 @*/
216$atomic_f int $message_tag($message message);
[7cdceea]217/*@ depends_on \nothing;
[7d856cc]218 @ executes_when $true;
219 @*/
220$atomic_f int $message_dest($message message);
[7cdceea]221/*@ depends_on \nothing;
[7d856cc]222 @ executes_when $true;
223 @*/
224$atomic_f int $message_size($message message);
[7cdceea]225/*@ depends_on \access(buf);
[7d856cc]226 @ executes_when $true;
227 @*/
228$atomic_f void $message_unpack($message message, void* buf, int size);
229/*@ depends_on \nothing;
[fccb5a6]230 @ assigns \nothing;
231 @ reads \nothing;
[7d856cc]232 @*/
[fccb5a6]233$atomic_f $gcomm $gcomm_create($scope scope, int size);
[7cdceea]234/*@ depends_on \access(junkMsgs), \access(gcomm);
[fccb5a6]235 @ assigns junkMsgs, gcomm;
[7d856cc]236 @*/
[fccb5a6]237$atomic_f int $gcomm_destroy($gcomm gcomm, void* junkMsgs);
[7cdceea]238/*@ depends_on \nothing;
239 @ reads gcomm;
240 @ assigns gcomm;
241 @*/
[6b88ea3]242$atomic_f $comm $comm_create($scope scope, $gcomm gcomm, int place);
[7cdceea]243/*@ depends_on \access(comm);
[fccb5a6]244 @ assigns comm;
245 @ reads \nothing;
[7d856cc]246 @*/
[fccb5a6]247$atomic_f void $comm_destroy($comm comm);
[7cdceea]248/*@ depends_on \nothing;
[7d856cc]249 @*/
[c3bddc1]250$atomic_f int $comm_size($comm comm);
[7cdceea]251/*@ depends_on \nothing;
[7d856cc]252 @ executes_when $true;
253 @*/
254$atomic_f int $comm_place($comm comm);
[7cdceea]255/*@ depends_on \access(comm);
[7d856cc]256 @ executes_when $true;
257 @*/
[39c2026]258$system[comm] void $comm_enqueue($comm comm, $message message);
[7cdceea]259/*@ depends_on \access(comm);
[c3bddc1]260 @ executes_when $true;
261 @*/
[e3ed948]262$system[comm] $state_f _Bool $comm_probe($comm comm, int source, int tag);
[7cdceea]263/*@ depends_on \access(comm);
[c3bddc1]264 @ executes_when $comm_probe(comm, source, tag);
[7d856cc]265 @*/
[39c2026]266$system[comm] $message $comm_dequeue($comm comm, int source, int tag);
[7cdceea]267//======================= collate.cvh ======================
268typedef struct _gcollator* $gcollator;
269typedef struct _collator* $collator;
270typedef struct _gcollate_state* $gcollate_state;
271$atomic_f $gcollator $gcollator_create($scope scope, int nprocs);
272$atomic_f $collator $collator_create($gcollator gcollator, $scope scope, int place);
[7d856cc]273//====================== civl-mpi.cvh ======================
274typedef struct $mpi_gcomm $mpi_gcomm;
[dba07d0]275$mpi_gcomm $mpi_gcomm_create($scope, int);
276void $mpi_gcomm_destroy($mpi_gcomm);
[f65e51c]277//========================= seq.cvl ========================
278$atomic_f void $seq_append(void* array, void* values, int count) {
279 int length = $seq_length(array);
280 $seq_insert(array, length, values, count);
281}
[7d856cc]282//===================== concurrency.cvl ====================
[c3bddc1]283struct _gbarrier{
[f65e51c]284 int nprocs;
285 $proc proc_map[];
286 _Bool in_barrier[];
287 int num_in_barrier;
[7d856cc]288};
[c3bddc1]289struct _barrier{
[f65e51c]290 int place;
291 $gbarrier gbarrier;
[7d856cc]292};
[f65e51c]293$atomic_f $gbarrier $gbarrier_create($scope scope, int size) {
[c3bddc1]294 $gbarrier gbarrier = ($gbarrier)($malloc(scope, sizeof(struct _gbarrier)));
[fccb5a6]295 (gbarrier)->nprocs = size;
[6e64101]296 (gbarrier)->proc_map = (($proc[size]) $lambda (int i) $proc_null);
297 (gbarrier)->in_barrier = ((_Bool[size]) $lambda (int i) 0);
[fccb5a6]298 (gbarrier)->num_in_barrier = 0;
299 return gbarrier;
300}
[f65e51c]301$atomic_f void $gbarrier_destroy($gbarrier gbarrier) {
[fccb5a6]302 $free(gbarrier);
303}
[f65e51c]304$atomic_f $barrier $barrier_create($scope scope, $gbarrier gbarrier, int place) {
[fccb5a6]305 $assert(((gbarrier)->proc_map[place]) == $proc_null, "the place %d in the global barrier has already been taken.", place);
[c3bddc1]306 $barrier barrier = ($barrier)($malloc(scope, sizeof(struct _barrier)));
[fccb5a6]307 (barrier)->place = place;
308 (barrier)->gbarrier = gbarrier;
309 (gbarrier)->proc_map[place] = $self;
310 return barrier;
311}
[f65e51c]312$atomic_f void $barrier_destroy($barrier barrier) {
[fccb5a6]313 $free(barrier);
314}
[f65e51c]315//====================== civl-mpi.cvl ======================
316char* $mpi_coroutine_name(int tag);
317struct $mpi_gcomm{
318 $gcomm p2p;
319 $gcomm col;
320 $gcollator gcollator;
321 $gbarrier gbarrier;
322};
323$mpi_gcomm $mpi_gcomm_create($scope scope, int size) {
324 $mpi_gcomm result;
325 result.p2p = $gcomm_create(scope, size);
326 result.col = $gcomm_create(scope, size);
[7cdceea]327 result.gcollator = $gcollator_create(scope, size);
[f65e51c]328 result.gbarrier = $gbarrier_create(scope, size);
329 return result;
330}
331void $mpi_gcomm_destroy($mpi_gcomm gc) {
332 int numJunkMsg;
333 $message junkMsgs[];
334 $seq_init(&(junkMsgs), 0, (void*)0);
335 numJunkMsg = $gcomm_destroy(gc.p2p, &(junkMsgs));
336 {
337 int i = 0;
338 for (; i < numJunkMsg; i = i + 1) {
339 int src;
340 int dest;
341 int tag;
342 src = $message_source(junkMsgs[i]);
343 dest = $message_dest(junkMsgs[i]);
344 tag = $message_tag(junkMsgs[i]);
[7cdceea]345 $assert(0, "MPI message leak: There is a message from rank %d to rank %d with tag %d has been sent but is never received in point-to-point communication.", src, dest, tag);
[f65e51c]346 }
347 }
348 numJunkMsg = $gcomm_destroy(gc.col, &(junkMsgs));
349 {
350 int i = 0;
351 for (; i < numJunkMsg; i = i + 1) {
352 int src;
353 int tag;
354 char* routine;
355 src = $message_source(junkMsgs[i]);
356 tag = $message_tag(junkMsgs[i]);
357 routine = $mpi_coroutine_name(tag);
[7cdceea]358 $assert(0, "MPI message leak: There is a message sent by rank %d for collective routine %s that is never received.", src, routine);
[f65e51c]359 }
360 }
[7cdceea]361 $free(gc.gcollator);
[f65e51c]362 $gbarrier_destroy(gc.gbarrier);
363}
364char* $mpi_coroutine_name(int tag) {
365 switch (tag) {
366 case 9999:
367 return "MPI_Bcast";
368 case 9998:
369 return "MPI_Reduce";
370 case 9997:
371 return "MPI_Allreduce";
372 case 9996:
373 return "MPI_Gather";
374 case 9995:
375 return "MPI_Scatter";
376 case 9994:
377 return "MPI_Gatherv";
378 case 9993:
379 return "MPI_Scatterv";
380 case 9992:
381 return "MPI_Allgather";
382 case 9991:
383 return "MPI_Reduce_scatter";
384 case 9990:
385 return "MPI_Alltoall";
386 case 9989:
387 return "MPI_Alltoallv";
388 case 9988:
389 return "MPI_Alltoallw";
390 case 9987:
391 return "MPI_Barrier";
392 case 9986:
393 return "MPI_Commdup";
394 case 9985:
395 return "MPI_Commfree";
396 default:
[7cdceea]397 $assert(0, "Internal Error: Unexpected MPI routine tag:%d.\n", tag);
[f65e51c]398 }
399}
400//======================== comm.cvl ========================
401struct _queue{
402 int length;
403 $message messages[];
404};
405struct _gcomm{
406 int nprocs;
407 $proc procs[];
408 _Bool isInit[];
409 $queue buf[][];
410};
411struct _comm{
412 int place;
413 $gcomm gcomm;
414};
415$atomic_f $message $message_pack(int source, int dest, int tag, void* data, int size) {
416 $message result;
417 result.source = source;
418 result.dest = dest;
419 result.tag = tag;
[7cdceea]420 if ((data != (void*)0) && (size > 0)) {
421 result.data = $bundle_pack(data, size);
422 }
423 else
424 if (data == (void*)0)
425 $assert(size == 0, "Attempt to pack a non-zero size message with a NULL pointer");
[f65e51c]426 result.size = size;
427 return result;
428}
429int $message_source($message message) {
430 return message.source;
431}
432int $message_tag($message message) {
433 return message.tag;
434}
435int $message_dest($message message) {
436 return message.dest;
437}
438int $message_size($message message) {
439 return message.size;
440}
441$atomic_f void $message_unpack($message message, void* buf, int size) {
[7cdceea]442 if ((buf != (void*)0) && (message.size > 0)) {
443 $bundle_unpack(message.data, buf);
444 $assert(message.size <= size, "Message of size %d exceeds the specified size %d.", message.size, size);
445 }
446 else
447 if (buf == (void*)0)
448 $assert(message.size == 0, "Attempt to unpack a non-zero size message with a NULL pointer.");
[f65e51c]449}
450$atomic_f $gcomm $gcomm_create($scope scope, int size) {
[c3bddc1]451 $gcomm gcomm = ($gcomm)($malloc(scope, sizeof(struct _gcomm)));
[fccb5a6]452 $queue empty;
453 empty.length = 0;
454 $seq_init(&(empty.messages), 0, (void*)0);
455 (gcomm)->nprocs = size;
[6e64101]456 (gcomm)->procs = (($proc[size]) $lambda (int i) $proc_null);
457 (gcomm)->isInit = ((_Bool[size]) $lambda (int i) 0);
458 (gcomm)->buf = (($queue[size][size]) $lambda (int i, j) empty);
[fccb5a6]459 return gcomm;
460}
[f65e51c]461$atomic_f int $gcomm_destroy($gcomm gcomm, void* junkMsgs) {
[c3bddc1]462 int nprocs = (gcomm)->nprocs;
463 int numJunks = 0;
[f65e51c]464 if (junkMsgs != (void*)0) {
[c3bddc1]465 {
466 int i = 0;
[f65e51c]467 for (; i < nprocs; i = i + 1) {
[c3bddc1]468 int j = 0;
[f65e51c]469 for (; j < nprocs; j = j + 1) {
[c3bddc1]470 $queue queue = (gcomm)->buf[i][j];
471 if (queue.length > 0)
472 $seq_append(junkMsgs, queue.messages, queue.length);
473 }
474 }
475 }
476 numJunks = $seq_length(junkMsgs);
477 }
[fccb5a6]478 $free(gcomm);
[c3bddc1]479 return numJunks;
[fccb5a6]480}
[f65e51c]481$atomic_f $comm $comm_create($scope scope, $gcomm gcomm, int place) {
[fccb5a6]482 $assert(!((gcomm)->isInit[place]), "the place %d is already occupied in the global communicator!", place);
[c3bddc1]483 $comm comm = ($comm)($malloc(scope, sizeof(struct _comm)));
[fccb5a6]484 (gcomm)->procs[place] = $self;
[7cdceea]485 (gcomm)->isInit[place] = 1;
[fccb5a6]486 (comm)->gcomm = gcomm;
487 (comm)->place = place;
488 return comm;
489}
[f65e51c]490$atomic_f void $comm_destroy($comm comm) {
[fccb5a6]491 $free(comm);
492}
[f65e51c]493$atomic_f int $comm_place($comm comm) {
[7d856cc]494 return (comm)->place;
495}
[f65e51c]496$atomic_f int $comm_size($comm comm) {
[c3bddc1]497 return ((comm)->gcomm)->nprocs;
498}
[7cdceea]499//======================= collate.cvl ======================
500struct _gcollator{
501 int nprocs;
502 $proc procs[];
503 int queue_length;
504 $gcollate_state queue[];
505 _Bool entered[];
506};
507struct _collator{
508 int place;
509 $gcollator gcollator;
510};
511struct _gcollate_state{
512 int status[];
513 $state state;
514 $bundle attribute;
515};
516$gcollator $gcollator_create($scope scope, int nprocs) {
517 $gcollator gcollator = ($gcollator)($malloc(scope, sizeof(struct _gcollator)));
518 (gcollator)->nprocs = nprocs;
[6e64101]519 (gcollator)->procs = (($proc[nprocs]) $lambda (int i) $proc_null);
[7cdceea]520 (gcollator)->queue_length = 0;
521 $seq_init(&((gcollator)->queue), 0, (void*)0);
[6e64101]522 (gcollator)->entered = ((_Bool[nprocs]) $lambda (int i) 0);
[7cdceea]523 return gcollator;
524}
525$collator $collator_create($gcollator gcollator, $scope scope, int place) {
526 $collator collator = ($collator)($malloc(scope, sizeof(struct _collator)));
527 (collator)->place = place;
528 (collator)->gcollator = gcollator;
529 ((collator)->gcollator)->procs[place] = $self;
530 return collator;
531}
[7d856cc]532//===================== MPITransformer =====================
533$input int _mpi_nprocs;
534$input int _mpi_nprocs_lo = 1;
535//======================= sum_array.c ======================
536$input int _mpi_nprocs_hi = 8;
537//===================== MPITransformer =====================
538$assume((_mpi_nprocs_lo <= _mpi_nprocs) && (_mpi_nprocs <= _mpi_nprocs_hi));
[c3bddc1]539$scope _mpi_root = $here;
540$mpi_gcomm _mpi_gcomm;
[7d856cc]541$mpi_gcomm _mpi_gcomms[];
[f65e51c]542void _mpi_process(int _mpi_rank) {
[7cdceea]543 /*@ depends_on \access(format);
544 @ executes_when $true;
[f65e51c]545 @*/
546 $system[stdio] int printf(char* restrict format, ...);
547 typedef struct MPI_Comm MPI_Comm;
548 MPI_Comm $mpi_comm_create($scope, $mpi_gcomm, int);
[7d856cc]549 MPI_Comm MPI_COMM_WORLD = $mpi_comm_create($here, _mpi_gcomm, _mpi_rank);
[f65e51c]550 typedef struct MPI_Status{
[7cdceea]551 int MPI_SOURCE;
552 int MPI_TAG;
553 int MPI_ERROR;
554 int size;
[f65e51c]555 } MPI_Status;
556 int MPI_Send(void*, int, MPI_Datatype, int, int, MPI_Comm);
557 int MPI_Recv(void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status*);
558 int MPI_Get_count(MPI_Status*, MPI_Datatype, int*);
559 int MPI_Comm_size(MPI_Comm, int*);
560 int MPI_Comm_rank(MPI_Comm, int*);
561 typedef enum _mpi_state{
[7cdceea]562 _MPI_UNINIT,
563 _MPI_INIT,
564 _MPI_FINALIZED
[f65e51c]565 } $mpi_state;
[6b88ea3]566 $mpi_state _mpi_state = _MPI_UNINIT;
[f65e51c]567 int $mpi_init(void) {
[6b88ea3]568 $assert(_mpi_state == _MPI_UNINIT, "Process can only call MPI_Init() at most once.");
569 _mpi_state = _MPI_INIT;
570 return 0;
571 }
[f65e51c]572 void $mpi_comm_destroy(MPI_Comm, $mpi_state);
573 int MPI_Finalize(void);
[7d856cc]574 double oracle;
575 void master(void);
576 void slave(void);
[f65e51c]577 int _civl_main(int argc, char** argv) {
[7d856cc]578 int myrank;
579 $mpi_init();
580 MPI_Comm_rank(MPI_COMM_WORLD, &(myrank));
581 if (!myrank)
582 master();
583 else
584 slave();
[6b88ea3]585 MPI_Finalize();
[7d856cc]586 return 0;
587 }
[f65e51c]588 void master(void) {
[7d856cc]589 float array[N];
590 double mysum;
591 double tmpsum;
592 unsigned long long step;
593 unsigned long long i;
594 int size;
595 MPI_Status status;
[7cdceea]596 for (i = $signed_to_unsigned(0, 4294967296); i < N; i = i + 1) {
597 unsigned long long $sef$12 = $signed_to_unsigned(1, 4294967296);
598 array[i] = i + $sef$12;
599 }
[7d856cc]600 oracle = 0.0;
[7cdceea]601 for (i = $signed_to_unsigned(0, 4294967296); i < N; i = i + 1)
[7d856cc]602 oracle = oracle + (array[i]);
603 MPI_Comm_size(MPI_COMM_WORLD, &(size));
604 if (size != 1)
[39c2026]605 step = $int_div(N, size - 1);
[7d856cc]606 else
607 step = N;
[7cdceea]608 for (i = $signed_to_unsigned(0, 4294967296); i < (size - 1); i = i + 1) {
609 unsigned long long $sef$13 = $signed_to_unsigned(1, 4294967296);
610 MPI_Send(array + (i * step), step, MPI_FLOAT, i + $sef$13, 100, MPI_COMM_WORLD);
611 }
[7d856cc]612 {
613 i = (size - 1) * step;
614 mysum = 0;
615 for (; i < N; i = i + 1)
616 mysum = mysum + (array[i]);
617 }
[7cdceea]618 for (i = $signed_to_unsigned(1, 4294967296); 1; ) {
619 unsigned long long $sef$14 = $signed_to_unsigned(size, 4294967296);
620 if (!(i < $sef$14))
621 break;
[7d856cc]622 MPI_Recv(&(tmpsum), 1, MPI_DOUBLE, -1, 101, MPI_COMM_WORLD, &(status));
623 mysum = mysum + tmpsum;
624 i = i + 1;
625 }
626 $assert(oracle == mysum, "The sum of %d array elements is %f but the expected one is %f.\n", N, mysum, oracle);
627 printf("%lf\n", mysum);
628 }
[f65e51c]629 void slave(void) {
[7d856cc]630 float array[N];
631 double sum;
632 unsigned long long i;
633 int count;
634 MPI_Status status;
635 MPI_Recv(array, N, MPI_FLOAT, 0, 100, MPI_COMM_WORLD, &(status));
636 MPI_Get_count(&(status), MPI_FLOAT, &(count));
637 {
[7cdceea]638 i = $signed_to_unsigned(0, 4294967296);
[7d856cc]639 sum = 0;
[7cdceea]640 for (; 1; i = i + 1) {
641 unsigned long long $sef$15 = $signed_to_unsigned(count, 4294967296);
642 if (!(i < $sef$15))
643 break;
[7d856cc]644 sum = sum + (array[i]);
[7cdceea]645 }
[7d856cc]646 }
647 MPI_Send(&(sum), 1, MPI_DOUBLE, 0, 101, MPI_COMM_WORLD);
648 }
[7cdceea]649 /*@ depends_on \nothing;
650 @ executes_when $true;
651 @*/
652 $atomic_f $state_f int sizeofDatatype(MPI_Datatype);
[f65e51c]653 int $mpi_send(void*, int, MPI_Datatype, int, int, MPI_Comm);
654 int $mpi_recv(void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status*);
[7cdceea]655 /*@ depends_on \access(buf);
656 @ executes_when $true;
[f65e51c]657 @*/
658 $system[mpi] void $mpi_check_buffer(void* buf, int count, MPI_Datatype datatype);
659 struct MPI_Comm{
[7cdceea]660 $comm p2p;
661 $comm col;
662 $collator collator;
663 $barrier barrier;
664 int gcommIndex;
[f65e51c]665 };
666 int MPI_Finalize(void) {
667 $assert(_mpi_state == _MPI_INIT, "Process can only call MPI_Finalize() after the MPI enviroment is created and before cleaned.");
668 _mpi_state = _MPI_FINALIZED;
669 return 0;
670 }
671 int MPI_Comm_size(MPI_Comm comm, int* size) {
672 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_size() cannot be invoked without MPI_Init() being called before.\n");
673 *size = $comm_size(comm.p2p);
674 return 0;
675 }
676 int MPI_Comm_rank(MPI_Comm comm, int* rank) {
677 $assert(_mpi_state == _MPI_INIT, "MPI_Comm_rank() cannot be invoked without MPI_Init() being called before.\n");
678 *rank = $comm_place(comm.p2p);
679 return 0;
680 }
681 int MPI_Send(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
682 $assert(_mpi_state == _MPI_INIT, "MPI_Send() cannot be invoked without MPI_Init() being called before.\n");
683 $mpi_check_buffer(buf, count, datatype);
[7cdceea]684 int $sef$16 = $mpi_send(buf, count, datatype, dest, tag, comm);
685 return $sef$16;
[f65e51c]686 }
687 int MPI_Recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status* status) {
688 $assert(_mpi_state == _MPI_INIT, "MPI_Recv() cannot be invoked without MPI_Init() being called before.\n");
[7cdceea]689 int $sef$17 = $mpi_recv(buf, count, datatype, source, tag, comm, status);
690 return $sef$17;
[f65e51c]691 }
692 int MPI_Get_count(MPI_Status* status, MPI_Datatype datatype, int* count) {
693 $assert(_mpi_state == _MPI_INIT, "MPI_Get_count() cannot be invoked without MPI_Init() being called before.\n");
[7cdceea]694 int $sef$18 = sizeofDatatype(datatype);
695 *count = $int_div((status)->size, $sef$18);
[f65e51c]696 return 0;
697 }
698 int sizeofDatatype(MPI_Datatype datatype) {
[7cdceea]699 size_t result;
[f65e51c]700 switch (datatype) {
701 case MPI_INT:
[7cdceea]702 result = sizeof(int);
703 break;
[f65e51c]704 case MPI_2INT:
[7cdceea]705 result = sizeof(int) * 2;
706 break;
[f65e51c]707 case MPI_FLOAT:
[7cdceea]708 result = sizeof(float);
709 break;
[f65e51c]710 case MPI_DOUBLE:
[7cdceea]711 result = sizeof(double);
712 break;
[f65e51c]713 case MPI_CHAR:
[7cdceea]714 result = sizeof(char);
715 break;
[f65e51c]716 case MPI_BYTE:
[7cdceea]717 result = sizeof(char);
718 break;
[f65e51c]719 case MPI_SHORT:
[7cdceea]720 result = sizeof(short);
721 break;
[f65e51c]722 case MPI_LONG:
[7cdceea]723 result = sizeof(long);
724 break;
[f65e51c]725 case MPI_LONG_DOUBLE:
[7cdceea]726 result = sizeof(long double);
727 break;
[f65e51c]728 case MPI_LONG_LONG_INT:
[7cdceea]729 result = sizeof(long long);
730 break;
[f65e51c]731 case MPI_LONG_LONG:
[7cdceea]732 result = sizeof(long long);
733 break;
[f65e51c]734 case MPI_UNSIGNED_LONG_LONG:
[7cdceea]735 result = sizeof(unsigned long long);
736 break;
[f65e51c]737 default:
738 $assert(0, "Unreachable");
739 }
[7cdceea]740 return result;
[f65e51c]741 }
742 MPI_Comm $mpi_comm_create($scope scope, $mpi_gcomm gc, int rank) {
743 MPI_Comm result;
744 result.p2p = $comm_create(scope, gc.p2p, rank);
745 result.col = $comm_create(scope, gc.col, rank);
[7cdceea]746 result.collator = $collator_create(gc.gcollator, scope, rank);
[f65e51c]747 result.barrier = $barrier_create(scope, gc.gbarrier, rank);
748 result.gcommIndex = 0;
749 return result;
750 }
751 void $mpi_comm_destroy(MPI_Comm comm, $mpi_state mpi_state) {
752 if (comm.gcommIndex == 0)
753 $assert(mpi_state == _MPI_FINALIZED, "Process terminates without calling MPI_Finalize() first.");
754 $comm_destroy(comm.p2p);
755 $comm_destroy(comm.col);
[7cdceea]756 $free(comm.collator);
[f65e51c]757 $barrier_destroy(comm.barrier);
758 }
759 int $mpi_send(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
[7cdceea]760 if ((dest >= 0) && (count >= 0)) {
761 int $sef$26 = sizeofDatatype(datatype);
762 int size = count * $sef$26;
[f65e51c]763 int place = $comm_place(comm.p2p);
[7cdceea]764 $message out;
765 $elaborate(dest);
766 out = $message_pack(place, dest, tag, buf, size);
[f65e51c]767 $comm_enqueue(comm.p2p, out);
768 }
769 return 0;
770 }
771 int $mpi_recv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status* status) {
[7cdceea]772 if (((source >= 0) || (source == (-1))) && (count >= 0)) {
[f65e51c]773 $message in;
774 int place = $comm_place(comm.p2p);
775 int deterministicTag;
776 $assert((tag == (-2)) || (tag >= 0), "Illegal MPI message receive tag %d.\n", tag);
777 deterministicTag = tag < 0 ? -2 : tag;
778 $elaborate(source);
779 in = $comm_dequeue(comm.p2p, source, deterministicTag);
[7cdceea]780 int $sef$27 = sizeofDatatype(datatype);
781 int size = count * $sef$27;
[f65e51c]782 $message_unpack(in, buf, size);
783 if (status != (void*)0) {
784 (status)->size = $message_size(in);
785 (status)->MPI_SOURCE = $message_source(in);
786 (status)->MPI_TAG = $message_tag(in);
787 (status)->MPI_ERROR = 0;
788 }
789 }
790 return 0;
791 }
[7d856cc]792 {
[6e64101]793 _civl_main(_civl_argc, ((char*[_civl_argc]) $lambda (int i) _civl_argv[i]));
[7d856cc]794 }
[6b88ea3]795 $mpi_comm_destroy(MPI_COMM_WORLD, _mpi_state);
[7d856cc]796}
[f65e51c]797int main() {
[c3bddc1]798 _mpi_gcomm = $mpi_gcomm_create(_mpi_root, _mpi_nprocs);
799 $seq_init(&(_mpi_gcomms), 1, &(_mpi_gcomm));
[7d856cc]800 $parfor (int i: 0 .. _mpi_nprocs - 1)
801 _mpi_process(i);
802 $mpi_gcomm_destroy(_mpi_gcomm);
803}
Note: See TracBrowser for help on using the repository browser.