6 integer,
target :: foobar
14 function upcase(s) result(ss)
17 character(kind=c_char,len=*),
intent(in) :: s
18 character(kind=c_char,len=len(s)) :: ss
20 character(*),
parameter :: uc =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" 21 character(*),
parameter :: lc =
"abcdefghijklmnopqrstuvwxyz" 25 if (n /= 0) ss(i:i) = uc(n:n)
29 integer(c_int) function addfivekeysfn(kv, kvi, kvo, p, i) bind(c) result(zz)
34 type(c_ptr),
value,
intent(in) :: kvi, kvo
35 type(c_ptr),
value,
intent(in) :: p
36 integer(c_long),
value,
intent(in) :: i
39 character(kind=c_char,len=1) :: strj
40 character(kind=c_char,len=5),
target :: k
41 character(kind=c_char,len=7),
target :: v
47 k = (c_char_
"key" // strj // c_null_char)
48 v = (c_char_
"value" // strj // c_null_char)
54 end function addfivekeysfn
56 integer(c_int) function replacevaluefn(kv, kvi, kvo, p, i) bind(c) result(zz)
62 type(c_ptr),
value,
intent(in) :: kvi, kvo
63 type(c_ptr),
value,
intent(in) :: p
64 integer(c_long),
value,
intent(in) :: i
66 character(kind=c_char,len=kv%vlen),
target :: v0
67 character(kind=c_char,len=kv%vlen),
target :: v1
76 end function replacevaluefn
78 integer(c_int) function starttaskfn(kv, kvi, kvo, p, i) bind(c) result(zz)
83 type(c_ptr),
value,
intent(in) :: kvi, kvo
84 type(c_ptr),
value,
intent(in) :: p
85 integer(c_long),
value,
intent(in) :: i
86 character(kind=c_char,len=kv%klen),
target :: k
87 character(kind=c_char,len=kv%vlen),
target :: v
88 integer(c_int) :: n, rank
92 print
"(A,A,A,A,A,A,I0)",
"Start master/slave task...", &
93 " key=", k(1:kv%klen-1), &
94 " value=", v(1:kv%vlen-1),
" rank=", rank
96 end function starttaskfn
98 integer(c_int) function printpairsfn(kv, n, kvi, kvo, p) bind(c) result(zz)
103 integer(c_long),
value,
intent(in) :: n
104 type(c_ptr),
value,
intent(in) :: kvi, kvo
105 type(c_ptr),
value,
intent(in) :: p
106 character(kind=c_char,len=5),
target :: k
107 character(kind=c_char,len=7),
target :: v
109 integer(c_int) :: nn, rank
111 print
"(A,I0,A,I0)",
"Reducing count=", n,
" rank=", rank
115 print
"(A,I0,A,A,A,A)",
"index=", i,
" key=", k(1:kv(i)%klen-1), &
116 " value=", v(1:kv(i)%vlen-1)
119 end function printpairsfn
121 integer(c_int) function addstructfn(kv, kvi, kvo, p, i) bind(c) result(zz)
126 type(c_ptr),
value,
intent(in) :: kvi, kvo
127 type(c_ptr),
value,
intent(in) :: p
128 integer(c_long),
value,
intent(in) :: i
130 character(kind=c_char,len=3) :: stra0
131 character(kind=c_char,len=3) :: stra1
132 character(kind=c_char,len=7),
target :: k
133 character(kind=c_char,len=9),
target :: v
134 type(
tuple2),
pointer :: ptr
135 call c_f_pointer(p, ptr)
136 write(stra0,
"(I3)") ptr%a0
137 write(stra1,
"(I3)") ptr%a1
138 k = (c_char_
"key" // stra0 // c_null_char)
139 v = (c_char_
"value" // stra1 // c_null_char)
145 end function addstructfn
147 integer(c_int) function addcommandsfn(kv, kvi, kvo, p, ii) bind(c) result(zz)
152 type(c_ptr),
value,
intent(in) :: kvi, kvo
153 type(c_ptr),
value,
intent(in) :: p
154 integer(c_long),
value,
intent(in) :: ii
156 character(kind=c_char,len=4),
target :: k
157 character(kind=c_char,len=100),
target :: v
158 character(kind=c_char,len=1),
target :: reply
160 if (c_associated(p))
then 166 nkv%vlen = (11 + 8 + 2 + 3 + 3 + 3)
167 k = (c_char_
"key" // c_null_char)
168 v = (c_char_
"maxprocs=2" // c_char_
" " &
169 // c_char_
"./a.out" // c_char_
" " &
170 // reply // c_char_
" " &
171 // c_char_
"a0" // c_char_
" " &
172 // c_char_
"a1" // c_char_
" " &
173 // c_char_
"a2" // c_null_char)
180 end function addcommandsfn
182 integer(c_int) function waitprocfn(kv, kvi, kvo, p, ii) bind(c) result(zz)
188 type(c_ptr),
value,
intent(in) :: kvi, kvo
189 type(c_ptr),
value,
intent(in) :: p
190 integer(c_long),
value,
intent(in) :: ii
196 print
"(A,(I0),A)",
"(waitprocfn sleeping(3)... icomm=", ic,
")" 200 end function waitprocfn
211 integer :: argc, ierr, rank, nprocs, thlv
212 character(len=128) argi
214 type(c_ptr) :: kvs0, kvs1, kvs2, kvs3, kvs4, kvs5
216 type(c_ptr) :: kvs20, kvs21, kvs22, kvs23, kvs24, kvs25
217 integer(c_long) :: cnt0, cnt1, cnt2, cnt3, cnt5
218 integer(c_int) :: opt
219 character(len=128) keepstack
220 integer :: parent, sz, peernprocs
221 logical :: maybespawned, needreply
223 character(len=MPI_MAX_PROCESSOR_NAME) :: name
225 type(
tuple2),
target :: tuple
230 call getenv(
"KEEPSTACK", keepstack)
231 if (keepstack(1:2) /=
"")
then 232 call signal(4, 1, sig)
233 call signal(6, 1, sig)
234 call signal(11, 1, sig)
241 maybespawned = .true.
243 maybespawned = .false.
246 call mpi_init_thread(mpi_thread_serialized, thlv, ierr);
247 call mpi_comm_rank(mpi_comm_world, rank, ierr)
248 call mpi_comm_size(mpi_comm_world, nprocs, ierr)
249 call mpi_get_processor_name(name, namelen, ierr)
253 if (maybespawned)
then 254 call mpi_comm_get_parent(parent, ierr)
255 if (parent == mpi_comm_null)
then 256 print *,
"NO PARENTS" 259 call mpi_comm_remote_size(parent, peernprocs, ierr)
260 call kmr_assert(peernprocs == 1,
"peernprocs == 1")
261 print *,
"Spawned process runs (", trim(name),
")..." 263 if (argi(1:1) ==
"0")
then 271 call mpi_send(sz, 0, mpi_byte, 0, 500, parent, ierr)
272 print *,
"(spawned process send reply (", trim(name),
"))" 274 call mpi_comm_free(parent, ierr)
275 call mpi_finalize(ierr)
276 print *,
"Spawned process runs (", trim(name),
") DONE" 292 call kmr_assert(cnt0 == 5,
"cnt0 == 5")
300 call kmr_assert(cnt1 == (5 * nprocs),
"cnt1 == (5 * nprocs)")
303 ierr =
kmr_map(kvs1, kvs2, c_null_ptr, 0, replacevaluefn)
306 if (rank == 0) print
"(A,I0)",
"cnt2=", cnt2
308 call kmr_assert(cnt2 == (5 * nprocs),
"cnt2 == (5 * nprocs)")
317 call kmr_assert(cnt3 == (5 * nprocs),
"cnt3 == (5 * nprocs)")
319 call kmr_assert(cnt3 == 0,
"cnt3 == 0")
323 opt = kmr_nothreading
326 ierr =
kmr_map_ms(kvs3, kvs4, c_null_ptr, opt, starttaskfn);
334 if (rank == 0) print
"(A,I0)",
"cnt5=", cnt5
335 call kmr_assert(cnt5 == (5 * nprocs),
"cnt5 == (5 * nprocs)")
339 ierr =
kmr_reduce(kvs5, c_null_ptr, c_null_ptr, 0, printpairsfn);
354 if (rank == 0) print *,
"Run spawn test with at least 4 dynamic processes" 359 if (rank == 0) print *,
"SPAWN WAITING IN MAP-FN" 365 opt = ior(kmr_one_by_one, kmr_separator_space)
367 mpi_info_null, opt, waitprocfn);
371 call mpi_barrier(mpi_comm_world, ierr);
376 if (rank == 0) print *,
"SPAWN WAITING WITH REPLY_EACH" 382 opt = ior(kmr_reply_each, kmr_separator_space)
384 mpi_info_null, opt, kmr_nullmapfn);
388 call mpi_barrier(mpi_comm_world, ierr);
392 if (rank == 0) print *,
"SPAWN NO WAITING" 393 if (rank == 0) print *,
"THIS PART FAILS WHEN LESS THAN 8 DYNAMIC PROCESSES" 399 opt = kmr_separator_space
401 mpi_info_null, opt, kmr_nullmapfn);
405 call mpi_barrier(mpi_comm_world, ierr);
407 if (rank == 0) print *,
"TEST DONE" 412 call mpi_finalize(ierr)
413 if (rank == 0) print *,
"OK" #define kmr_reduce(KVI, KVO, ARG, OPT, R)
Reduces key-value pairs.
Converts in reverse of kmr_strint().
#define kmr_create_kvs(MR, KF, VF)
Makes a new key-value stream (of type KMR_KVS) with the specified field datatypes.
(See kmr_get_context_of_kvs() in C).
MPI_Comm * kmr_get_spawner_communicator(KMR *mr, long index)
Obtains (a reference to) a parent inter-communicator of a spawned process.
int kmr_shuffle(KMR_KVS *kvi, KMR_KVS *kvo, struct kmr_option opt)
Shuffles key-value pairs to the appropriate destination ranks.
(See kmr_free_context() in C).
Returns the element count local on each node.
Gets MPI rank from a key-value stream.
#define kmr_map(KVI, KVO, ARG, OPT, M)
Maps simply.
Handy Copy of a Key-Value Field.
(See kmr_get_element_count() in C).
#define kmr_init()
Sets up the environment.
(See kmr_free_kvs() in C).
int kmr_map_via_spawn(KMR_KVS *kvi, KMR_KVS *kvo, void *arg, MPI_Info info, struct kmr_spawn_option opt, kmr_mapfn_t mapfn)
Maps on processes started by MPI_Comm_spawn().
int kmr_map_ms(KMR_KVS *kvi, KMR_KVS *kvo, void *arg, struct kmr_option opt, kmr_mapfn_t m)
Maps in master-slave mode.
int kmr_replicate(KMR_KVS *kvi, KMR_KVS *kvo, struct kmr_option opt)
Replicates key-value pairs to be visible on all ranks, that is, it has the effect of bcast or all-gat...
Converts a character array to a (pointer value) integer for key/value (it is casting in C)...
(See kmr_dump_kvs() in C).
int kmr_map_on_rank_zero(KMR_KVS *kvo, void *arg, struct kmr_option opt, kmr_mapfn_t m)
Maps on rank0 only.
KMR * kmr_create_context(const MPI_Comm comm, const MPI_Info conf, const char *name)
Makes a new KMR context (a context has type KMR).