cslmpi.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /* cslmpi.c */
  2. /*
  3. * Interfaces for mpi from CSL. The bulk of this code was written by
  4. * M O Seymour (1997-98) who has released it for inclusion as part of
  5. * this Lisp system.
  6. */
  7. /*
  8. * This code may be used and modified, and redistributed in binary
  9. * or source form, subject to the "CCL Public License", which should
  10. * accompany it. This license is a variant on the BSD license, and thus
  11. * permits use of code derived from this in either open and commercial
  12. * projects: but it does require that updates to this code be made
  13. * available back to the originators of the package.
  14. * Before merging other code in with this or linking this code
  15. * with other packages or libraries please check that the license terms
  16. * of the other material are compatible with those of this.
  17. */
  18. /* Signature: 55e2c6ac 10-Oct-2002 */
  19. #include <stdarg.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include "machine.h"
  23. #include "tags.h"
  24. #include "cslerror.h"
  25. #include "externs.h"
  26. #include "arith.h"
  27. #include "entries.h"
  28. #ifdef TIMEOUT
  29. #include "timeout.h"
  30. #endif
  31. #ifdef USE_MPI
  32. #include "read.h"
  33. #include "mpipack.c"
  34. #define check_fix(v) if (!is_fixnum(v)) return aerror1(fun_name, v)
  35. #define get_arg(v) v = va_arg(a,Lisp_Object)
  36. #define get_fix_arg(v) get_arg(v); check_fix(v); v=int_of_fixnum(v)
  37. /************************ Environmental functions *******************/
  38. /* Returns process rank
  39. * (mpi_comm_rank comm)
  40. */
  41. /* For now, I assume that comm will fit into a fixnum.
  42. * This appears to be the case with MPICH (values in the hundreds),
  43. * but assumptions like this should not be made.
  44. */
  45. static Lisp_Object Lmpi_comm_rank(Lisp_Object nil, Lisp_Object comm)
  46. {
  47. int rank;
  48. static char fun_name[] = "mpi_comm_rank";
  49. CSL_IGNORE(nil);
  50. check_fix(comm);
  51. MPI_Comm_rank(int_of_fixnum(comm),&rank);
  52. return onevalue(fixnum_of_int(rank));
  53. }
  54. /* returns size of communicator
  55. * (mpi_comm_size comm)
  56. */
  57. /* Same assumption about comm. */
  58. static Lisp_Object Lmpi_comm_size(Lisp_Object nil, Lisp_Object comm)
  59. {
  60. int size;
  61. static char fun_name[] = "mpi_comm_size";
  62. CSL_IGNORE(nil);
  63. check_fix(comm);
  64. MPI_Comm_size(int_of_fixnum(comm),&size);
  65. return onevalue(fixnum_of_int(size));
  66. }
  67. /********************** Blocking point-to-point functions *************/
  68. /* Standard blocking send
  69. * (mpi_send message dest tag comm)
  70. * returns nil.
  71. */
  72. /* Same assumption about comm. */
  73. static Lisp_Object MS_CDECL Lmpi_send(Lisp_Object nil, int nargs, ...)
  74. {
  75. static char fun_name[] = "mpi_send";
  76. Lisp_Object message;
  77. int dest,tag,comm;
  78. va_list a;
  79. argcheck(nargs,4,fun_name);
  80. va_start(a,nargs);
  81. get_arg(message);
  82. get_fix_arg(dest); get_fix_arg(tag); get_fix_arg(comm);
  83. pack_object(message);
  84. MPI_Send(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  85. dest, tag, comm);
  86. free(mpi_pack_buffer);
  87. return onevalue(nil);
  88. }
  89. /* Standard blocking receive
  90. * (mpi_recv source tag comm)
  91. * returns (message (source tag error)).
  92. */
  93. static Lisp_Object MS_CDECL Lmpi_recv(Lisp_Object nil, int nargs, ...)
  94. {
  95. static char fun_name[] = "mpi_recv";
  96. MPI_Status status;
  97. int source,tag,comm;
  98. Lisp_Object Lstatus;
  99. va_list a;
  100. CSL_IGNORE(nil);
  101. argcheck(nargs,3,fun_name);
  102. va_start(a,nargs);
  103. get_fix_arg(source); get_fix_arg(tag); get_fix_arg(comm);
  104. MPI_Probe(source, tag, comm, &status);
  105. MPI_Get_count(&status, MPI_PACKED, &mpi_pack_size);
  106. mpi_pack_buffer = (char*)malloc(mpi_pack_size);
  107. MPI_Recv(mpi_pack_buffer, mpi_pack_size, MPI_PACKED,
  108. source, tag, comm, &status);
  109. /* The only relevant status things are the 3 public fields, so I'll
  110. * stick them in a list and return them as the 2nd value
  111. */
  112. push(unpack_object());
  113. free(mpi_pack_buffer);
  114. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  115. fixnum_of_int(status.MPI_TAG),
  116. fixnum_of_int(status.MPI_ERROR));
  117. return onevalue(list2(my_pop(),Lstatus));
  118. }
  119. /* Standard blocking simultaneous send and receive
  120. * (mpi_sendrecv send_message dest send_tag source recv_tag comm)
  121. * returns (recv_message (source recv_tag error))
  122. */
  123. /* THERE IS A LIMIT OF 1024 BYTES FOR THE RECEIVE BUFFER (sorry.)
  124. * THIS WILL BE REMOVED ASAP.
  125. */
  126. static Lisp_Object MS_CDECL Lmpi_sendrecv(Lisp_Object nil, int nargs, ...)
  127. {
  128. static char fun_name[] = "mpi_sendrecv";
  129. MPI_Status status;
  130. Lisp_Object Lstatus;
  131. Lisp_Object s_mess;
  132. int s_tag, r_tag, dest, source, comm;
  133. char r_buffer[1024];
  134. va_list a;
  135. CSL_IGNORE(nil);
  136. argcheck(nargs,6,fun_name);
  137. va_start(a,nargs);
  138. get_arg(s_mess);
  139. get_fix_arg(dest); get_fix_arg(s_tag);
  140. get_fix_arg(source); get_fix_arg(r_tag); get_fix_arg(comm);
  141. pack_object(s_mess);
  142. MPI_Sendrecv(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  143. dest, s_tag,
  144. r_buffer, 1024, MPI_PACKED,
  145. source, r_tag, comm, &status);
  146. free(mpi_pack_buffer);
  147. mpi_pack_buffer = r_buffer;
  148. push(unpack_object());
  149. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  150. fixnum_of_int(status.MPI_TAG),
  151. fixnum_of_int(status.MPI_ERROR));
  152. return onevalue(list2(my_pop(),Lstatus));
  153. }
  154. /************** Non-Blocking point-to-point functions ***********/
  155. /* Standard non-blocking send post
  156. * (mpi_isend message dest tag comm)
  157. * returns request handle
  158. */
  159. static Lisp_Object MS_CDECL Lmpi_isend(Lisp_Object nil, int nargs, ...)
  160. {
  161. static char fun_name[] = "mpi_isend";
  162. Lisp_Object message, request;
  163. int dest, tag, comm;
  164. va_list a;
  165. CSL_IGNORE(nil);
  166. /* For now, we assume type MPI_Request to be 32 bits. */
  167. request = Lmkvect32(nil,fixnum_of_int(2));
  168. argcheck(nargs,4,fun_name);
  169. va_start(a,nargs);
  170. get_arg(message);
  171. get_fix_arg(dest); get_fix_arg(tag); get_fix_arg(comm);
  172. pack_object(message);
  173. MPI_Isend(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  174. dest, tag, comm, (MPI_Request*)&elt(request,0));
  175. elt(request,1) = (int)mpi_pack_buffer;
  176. return onevalue(request);
  177. }
  178. /* Standard non-blocking receive post
  179. * (mpi_irecv source tag comm)
  180. * returns request handle
  181. */
  182. /* I actually cheat horribly by not posting the request at all (at least
  183. * not via MPI), but rather create my own "dummy" request structure.
  184. * Then, to complete the request, I MPI_(I)Probe for a matching message,
  185. * and receive it if it is there.
  186. * This is unsatisfactory since the operation is only non-blocking until the
  187. * first lump of the message arrives; for a long message, there may by
  188. * a lot of latency after this.
  189. */
  190. struct dummy_request{
  191. int source;
  192. int tag;
  193. int comm;
  194. };
  195. static Lisp_Object MS_CDECL Lmpi_irecv(Lisp_Object nil, int nargs, ...)
  196. {
  197. static char fun_name[] = "mpi_irecv";
  198. int source,tag,comm;
  199. Lisp_Object request;
  200. va_list a;
  201. char* buffer;
  202. CSL_IGNORE(nil);
  203. /* For now, we assume type MPI_Request to be 32 bits. */
  204. request = Lmkvect32(nil,fixnum_of_int(2));
  205. argcheck(nargs,3,fun_name);
  206. va_start(a,nargs);
  207. get_fix_arg(source); get_fix_arg(tag); get_fix_arg(comm);
  208. elt(request,1) = 0; /* There is no buffer yet */
  209. elt(request,0) = (int)malloc(sizeof(struct dummy_request));
  210. ((struct dummy_request*)elt(request,0))->source = source;
  211. ((struct dummy_request*)elt(request,0))->tag = tag;
  212. ((struct dummy_request*)elt(request,0))->comm = comm;
  213. return onevalue(request);
  214. }
  215. /* Wait to complete operation, and deallocate buffer.
  216. * (mpi_wait request)
  217. * for send, returns nil
  218. * for recv, returns (message (source tag error))
  219. */
  220. static Lisp_Object Lmpi_wait(Lisp_Object nil, Lisp_Object request)
  221. {
  222. MPI_Status status;
  223. Lisp_Object message, Lstatus;
  224. if ( !(is_vector(request) && type_of_header(vechdr(request)) == TYPE_VEC32 &&
  225. length_of_header(vechdr(request)) == 3*CELL) )
  226. return aerror1("mpi_wait",request);
  227. if ( elt(request,1)){
  228. status.MPI_ERROR = MPI_UNDEFINED;
  229. mpi_pack_buffer = (void*)elt(request,1);
  230. MPI_Wait( (MPI_Request*)&elt(request,0), &status);
  231. if (status.MPI_ERROR == MPI_UNDEFINED){ /* i.e. send request */
  232. free(mpi_pack_buffer);
  233. return onevalue(nil);
  234. }
  235. else { /* old-style receive */
  236. push(unpack_object());
  237. free(mpi_pack_buffer);
  238. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  239. fixnum_of_int(status.MPI_TAG),
  240. fixnum_of_int(status.MPI_ERROR));
  241. return onevalue(list2(my_pop(),Lstatus));
  242. }
  243. }
  244. else{ /* new-style receive */
  245. int source = ((struct dummy_request*)elt(request,0))->source,
  246. tag = ((struct dummy_request*)elt(request,0))->tag,
  247. comm = ((struct dummy_request*)elt(request,0))->comm;
  248. MPI_Probe(source, tag, comm, &status);
  249. free((struct dummy_request*)elt(request,0));
  250. MPI_Get_count(&status, MPI_PACKED, &mpi_pack_size);
  251. mpi_pack_buffer = (char*)malloc(mpi_pack_size);
  252. MPI_Recv(mpi_pack_buffer, mpi_pack_size, MPI_PACKED,
  253. source, tag, comm, &status);
  254. /* The only relevant status things are the 3 public fields, so I'll
  255. * stick them in a list and return them as the 2nd value
  256. */
  257. push(unpack_object());
  258. free(mpi_pack_buffer);
  259. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  260. fixnum_of_int(status.MPI_TAG),
  261. fixnum_of_int(status.MPI_ERROR));
  262. return onevalue(list2(my_pop(),Lstatus));
  263. }
  264. }
  265. /* Test for completion, deallocate buffer if so
  266. * (mpi_test request)
  267. * for send, returns flag
  268. * for recv, returns nil or (message (source tag error))
  269. */
  270. static Lisp_Object Lmpi_test(Lisp_Object nil, Lisp_Object request)
  271. {
  272. MPI_Status status;
  273. Lisp_Object message, Lstatus;
  274. int flag;
  275. if ( !(is_vector(request) && type_of_header(vechdr(request)) == TYPE_VEC32 &&
  276. length_of_header(vechdr(request)) == 3*CELL) )
  277. return aerror1("mpi_wait",request);
  278. if (elt(request,1)){
  279. status.MPI_ERROR = MPI_UNDEFINED;
  280. mpi_pack_buffer = (void*)elt(request,1);
  281. MPI_Test( (MPI_Request*)&elt(request,0), &flag, &status);
  282. if (!flag) return onevalue(nil);
  283. if (status.MPI_ERROR == MPI_UNDEFINED){ /* send request */
  284. free(mpi_pack_buffer);
  285. return onevalue(Lispify_predicate(YES));
  286. }
  287. else{ /* old-style receive */
  288. push(unpack_object());
  289. free(mpi_pack_buffer);
  290. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  291. fixnum_of_int(status.MPI_TAG),
  292. fixnum_of_int(status.MPI_ERROR));
  293. return onevalue(list2(my_pop(),Lstatus));
  294. }
  295. }
  296. else { /* new-style receive */
  297. int source = ((struct dummy_request*)elt(request,0))->source,
  298. tag = ((struct dummy_request*)elt(request,0))->tag,
  299. comm = ((struct dummy_request*)elt(request,0))->comm, flag;
  300. MPI_Iprobe(source, tag, comm, &flag, &status);
  301. if (!flag) return onevalue(nil);
  302. free((struct dummy_request*)elt(request,0));
  303. MPI_Get_count(&status, MPI_PACKED, &mpi_pack_size);
  304. mpi_pack_buffer = (char*)malloc(mpi_pack_size);
  305. MPI_Recv(mpi_pack_buffer, mpi_pack_size, MPI_PACKED,
  306. source, tag, comm, &status);
  307. /* The only relevant status things are the 3 public fields, so I'll
  308. * stick them in a list and return them as the 2nd value
  309. */
  310. push(unpack_object());
  311. free(mpi_pack_buffer);
  312. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  313. fixnum_of_int(status.MPI_TAG),
  314. fixnum_of_int(status.MPI_ERROR));
  315. return onevalue(list2(my_pop(),Lstatus));
  316. }
  317. }
  318. /************** Probe functions *******************/
  319. /* Non-blocking probe
  320. * (mpi_iprobe source tag comm)
  321. * returns (flag (source tag error))
  322. */
  323. static Lisp_Object MS_CDECL Lmpi_iprobe(Lisp_Object nil, int nargs, ...)
  324. {
  325. static char fun_name[] = "impi_probe";
  326. MPI_Status status;
  327. int source, tag, comm, flag;
  328. Lisp_Object Lstatus;
  329. va_list a;
  330. CSL_IGNORE(nil);
  331. argcheck(nargs,3,fun_name);
  332. va_start(a,nargs);
  333. get_fix_arg(source); get_fix_arg(tag); get_fix_arg(comm);
  334. MPI_Iprobe(source, tag, comm, &flag, &status);
  335. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  336. fixnum_of_int(status.MPI_TAG),
  337. fixnum_of_int(status.MPI_ERROR));
  338. return onevalue(list2(Lispify_predicate(flag), Lstatus));
  339. }
  340. /* Blocking probe
  341. * (mpi_probe source tag comm)
  342. * returns (source tag error)
  343. */
  344. static Lisp_Object MS_CDECL Lmpi_probe(Lisp_Object nil, int nargs, ...)
  345. {
  346. static char fun_name[] = "mpi_probe";
  347. MPI_Status status;
  348. int source, tag, comm;
  349. Lisp_Object Lstatus;
  350. va_list a;
  351. CSL_IGNORE(nil);
  352. argcheck(nargs,3,fun_name);
  353. va_start(a,nargs);
  354. get_fix_arg(source); get_fix_arg(tag); get_fix_arg(comm);
  355. MPI_Probe(source, tag, comm, &status);
  356. Lstatus = list3(fixnum_of_int(status.MPI_SOURCE),
  357. fixnum_of_int(status.MPI_TAG),
  358. fixnum_of_int(status.MPI_ERROR));
  359. return onevalue(Lstatus);
  360. }
  361. /************** Collective Communications *********/
  362. /* Barrier; blocks until all processes have called
  363. * (mpi_barrier comm)
  364. * returns nil
  365. */
  366. static Lisp_Object Lmpi_barrier(Lisp_Object nil, Lisp_Object comm)
  367. {
  368. int rank;
  369. static char fun_name[] = "mpi_barrier";
  370. check_fix(comm);
  371. MPI_Barrier(int_of_fixnum(comm));
  372. return onevalue(nil);
  373. }
  374. /* Broadcast; sends buffer of root to buffers of others.
  375. * (mpi_bcast message root comm) [message ignored if not root]
  376. * returns message
  377. */
  378. static Lisp_Object MS_CDECL Lmpi_bcast(Lisp_Object nil, int nargs, ...)
  379. {
  380. static char fun_name[] = "mpi_bcast";
  381. Lisp_Object message;
  382. int root,comm,rank;
  383. va_list a;
  384. CSL_IGNORE(nil);
  385. argcheck(nargs,3,fun_name);
  386. va_start(a,nargs);
  387. get_arg(message); get_fix_arg(root); get_fix_arg(comm);
  388. MPI_Comm_rank(comm,&rank);
  389. if (rank == root){
  390. pack_object(message);
  391. MPI_Bcast(&mpi_pack_position, 1, MPI_LONG, root, comm);
  392. MPI_Bcast(mpi_pack_buffer, mpi_pack_position, MPI_PACKED, root, comm);
  393. free(mpi_pack_buffer);
  394. }
  395. else {
  396. MPI_Bcast(&mpi_pack_size, 1, MPI_LONG, root, comm);
  397. mpi_pack_buffer = (char*)malloc(mpi_pack_size);
  398. MPI_Bcast(mpi_pack_buffer, mpi_pack_size, MPI_PACKED, root, comm);
  399. message = unpack_object();
  400. free(mpi_pack_buffer);
  401. }
  402. return onevalue(message);
  403. }
  404. /* Gather: root receives messages from others.
  405. * (mpi_gather message root comm)
  406. * returns vector of messages if root, else nil.
  407. */
  408. static Lisp_Object MS_CDECL Lmpi_gather(Lisp_Object nil, int nargs, ...)
  409. {
  410. static char fun_name[] = "mpi_gather";
  411. Lisp_Object message;
  412. int root,comm,rank;
  413. va_list a;
  414. CSL_IGNORE(nil);
  415. argcheck(nargs,3,fun_name);
  416. va_start(a,nargs);
  417. get_arg(message); get_fix_arg(root); get_fix_arg(comm);
  418. MPI_Comm_rank(comm,&rank);
  419. pack_object(message);
  420. if (rank == root){
  421. int commsize, count;
  422. int *recvcounts, *displs;
  423. char *recvbuffer;
  424. MPI_Comm_size(comm,&commsize);
  425. recvcounts = (int*)calloc(commsize, sizeof(int));
  426. displs = (int*)calloc(commsize+1, sizeof(int));
  427. MPI_Gather(&mpi_pack_position, 1, MPI_LONG,
  428. recvcounts, 1, MPI_LONG, root, comm);
  429. displs[0] = 0;
  430. for (count = 0; count < commsize; ++count)
  431. displs[count+1] = displs[count] + recvcounts[count];
  432. recvbuffer = (char*)malloc(displs[commsize]);
  433. MPI_Gatherv(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  434. recvbuffer, recvcounts, displs, MPI_PACKED, root, comm);
  435. free(mpi_pack_buffer);
  436. message = Lmkvect(nil, fixnum_of_int(commsize-1));
  437. for (count = 0; count < commsize; ++count){
  438. mpi_pack_buffer = recvbuffer + displs[count];
  439. mpi_pack_size = recvcounts[count];
  440. elt(message, count) = unpack_object();
  441. }
  442. free(recvbuffer); free(recvcounts); free(displs);
  443. }
  444. else {
  445. MPI_Gather(&mpi_pack_position, 1, MPI_LONG, 0, 0, MPI_LONG, root, comm);
  446. MPI_Gatherv(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  447. 0,0,0,MPI_PACKED, root, comm);
  448. free(mpi_pack_buffer);
  449. message = nil;
  450. }
  451. return onevalue(message);
  452. }
  453. /* Scatter: inverse of gather.
  454. * (mpi_scatter vector_of_messages root comm) [messages ignored if not root]
  455. * returns message
  456. */
  457. static Lisp_Object MS_CDECL Lmpi_scatter(Lisp_Object nil, int nargs, ...)
  458. {
  459. static char fun_name[] = "mpi_scatter";
  460. Lisp_Object messages, message;
  461. int root, comm, rank;
  462. va_list a;
  463. CSL_IGNORE(nil);
  464. argcheck(nargs,3,fun_name);
  465. va_start(a,nargs);
  466. get_arg(messages); get_fix_arg(root); get_fix_arg(comm);
  467. MPI_Comm_rank(comm,&rank);
  468. if (rank == root){
  469. int commsize, count, *sendcounts, *displs, recvcount;
  470. char* recvbuffer;
  471. MPI_Comm_size(comm,&commsize);
  472. sendcounts = (int*)calloc(commsize, sizeof(int));
  473. displs = (int*)calloc(commsize+1, sizeof(int));
  474. displs[0] = 0;
  475. /* Call private functions in mpi_packing for consecutive packs */
  476. check_buffer = scatter_check_buffer;
  477. mpi_pack_offset = 0;
  478. mpi_pack_position = 0;
  479. mpi_pack_size = 0;
  480. mpi_buffer_bottom = 0;
  481. mpi_real_size = 0;
  482. for (count = 0; count < commsize; ++count){
  483. pack_cell(elt(messages,count));
  484. sendcounts[count] = mpi_pack_position;
  485. mpi_pack_size -= mpi_pack_position;
  486. mpi_pack_offset += mpi_pack_position;
  487. mpi_pack_buffer += mpi_pack_position;
  488. displs[count+1] = mpi_pack_offset;
  489. mpi_pack_position = 0;
  490. }
  491. check_buffer = default_check_buffer;
  492. MPI_Scatter(sendcounts, 1, MPI_LONG, &recvcount, 1, MPI_LONG, root, comm);
  493. recvbuffer = (char*)malloc(recvcount);
  494. MPI_Scatterv(mpi_buffer_bottom, sendcounts, displs, MPI_PACKED,
  495. recvbuffer, recvcount, MPI_PACKED, root, comm);
  496. free(recvbuffer);
  497. free(sendcounts);
  498. free(displs);
  499. free(mpi_buffer_bottom);
  500. message = elt(messages, root);
  501. }
  502. else {
  503. MPI_Scatter(0,0,MPI_LONG,&mpi_pack_size,1,MPI_LONG,root,comm);
  504. mpi_pack_buffer = (char*)malloc(mpi_pack_size);
  505. MPI_Scatterv(0,0,0,MPI_PACKED,
  506. mpi_pack_buffer,mpi_pack_size,MPI_PACKED,root,comm);
  507. message = unpack_object();
  508. free(mpi_pack_buffer);
  509. }
  510. return onevalue(message);
  511. }
  512. /* Allgather: just like gather, only everyone gets the result.
  513. * (mpi_allgather message comm)
  514. * returns vector of messages
  515. */
  516. static Lisp_Object Lmpi_allgather(Lisp_Object nil,
  517. Lisp_Object message,
  518. Lisp_Object comm)
  519. {
  520. static char fun_name[] = "mpi_gather";
  521. int commsize, buffersize, count;
  522. int *recvcounts, *displs;
  523. char *recvbuffer;
  524. check_fix(comm);
  525. comm = int_of_fixnum(comm);
  526. CSL_IGNORE(nil);
  527. pack_object(message);
  528. MPI_Comm_size(comm,&commsize);
  529. recvcounts = (int*)calloc(commsize, sizeof(int));
  530. displs = (int*)calloc(commsize+1, sizeof(int));
  531. MPI_Allgather(&mpi_pack_position, 1, MPI_LONG, recvcounts, 1, MPI_LONG, comm);
  532. displs[0] = 0;
  533. for (count = 0; count < commsize; ++count)
  534. displs[count+1] = displs[count] + recvcounts[count];
  535. recvbuffer = (char*)malloc(displs[commsize]);
  536. MPI_Allgatherv(mpi_pack_buffer, mpi_pack_position, MPI_PACKED,
  537. recvbuffer, recvcounts, displs, MPI_PACKED, comm);
  538. free(mpi_pack_buffer); free(recvcounts); free(displs);
  539. message = Lmkvect(nil, fixnum_of_int(commsize-1));
  540. for (count = 0; count < commsize; ++count){
  541. mpi_pack_buffer = recvbuffer + displs[count];
  542. mpi_pack_size = recvcounts[count];
  543. elt(message, count) = unpack_object();
  544. }
  545. free(recvbuffer);
  546. return onevalue(message);
  547. }
  548. /* All to all scatter/gather.
  549. * (mpi_alltoall vector_of_messages comm)
  550. * returns vector of messages.
  551. */
  552. static Lisp_Object Lmpi_alltoall(Lisp_Object nil,
  553. Lisp_Object smessages, Lisp_Object Lcomm)
  554. {
  555. static char fun_name[] = "mpi_alltoall";
  556. Lisp_Object rmessages;
  557. int rank,comm, commsize, count;
  558. int *sendcounts, *recvcounts, *sdispls, *rdispls;
  559. char* recvbuffer;
  560. CSL_IGNORE(nil);
  561. check_fix(Lcomm);
  562. comm = int_of_fixnum(Lcomm);
  563. MPI_Comm_size(comm,&commsize);
  564. sendcounts = (int*)calloc(commsize, sizeof(int));
  565. recvcounts = (int*)calloc(commsize, sizeof(int));
  566. sdispls = (int*)calloc(commsize+1, sizeof(int));
  567. rdispls = (int*)calloc(commsize+1, sizeof(int));
  568. /* Call private functions in mpi_packing for consecutive packs */
  569. check_buffer = scatter_check_buffer;
  570. mpi_pack_offset = 0;
  571. mpi_pack_position = 0;
  572. mpi_pack_size = 0;
  573. mpi_buffer_bottom = 0;
  574. mpi_real_size = 0;
  575. for (count = 0; count < commsize; ++count){
  576. pack_cell(elt(smessages,count));
  577. sendcounts[count] = mpi_pack_position;
  578. mpi_pack_size -= mpi_pack_position;
  579. mpi_pack_offset += mpi_pack_position;
  580. mpi_pack_buffer += mpi_pack_position;
  581. sdispls[count+1] = mpi_pack_offset;
  582. mpi_pack_position = 0;
  583. }
  584. check_buffer = default_check_buffer;
  585. MPI_Comm_rank(comm,&rank);
  586. MPI_Alltoall(sendcounts, 1, MPI_LONG, recvcounts, 1, MPI_LONG, comm);
  587. rdispls[0] = 0;
  588. for (count = 0; count < commsize; ++count)
  589. rdispls[count+1] = rdispls[count] + recvcounts[count];
  590. recvbuffer = (char*)malloc(rdispls[commsize]);
  591. MPI_Alltoallv(mpi_buffer_bottom, sendcounts, sdispls, MPI_PACKED,
  592. recvbuffer, recvcounts, rdispls, MPI_PACKED, comm);
  593. free(mpi_buffer_bottom); free(sendcounts); free(sdispls);
  594. rmessages = Lmkvect(nil, fixnum_of_int(commsize-1));
  595. for (count = 0; count < commsize; ++count){
  596. mpi_pack_buffer = recvbuffer + rdispls[count];
  597. mpi_pack_size = recvcounts[count];
  598. elt(rmessages, count) = unpack_object();
  599. }
  600. free(recvbuffer); free(recvcounts); free(rdispls);
  601. return onevalue(rmessages);
  602. }
  603. #else /* USE_MPI */
  604. static Lisp_Object Lmpi_comm_rank(Lisp_Object nil, Lisp_Object comm)
  605. {
  606. CSL_IGNORE(nil);
  607. CSL_IGNORE(comm);
  608. return aerror0("mpi support not built into this version of CSL");
  609. }
  610. static Lisp_Object Lmpi_comm_size(Lisp_Object nil, Lisp_Object comm)
  611. {
  612. CSL_IGNORE(nil);
  613. CSL_IGNORE(comm);
  614. return aerror0("mpi support not built into this version of CSL");
  615. }
  616. static Lisp_Object MS_CDECL Lmpi_send(Lisp_Object nil, int nargs, ...)
  617. {
  618. CSL_IGNORE(nil);
  619. CSL_IGNORE(nargs);
  620. return aerror0("mpi support not built into this version of CSL");
  621. }
  622. static Lisp_Object MS_CDECL Lmpi_recv(Lisp_Object nil, int nargs, ...)
  623. {
  624. CSL_IGNORE(nil);
  625. CSL_IGNORE(nargs);
  626. return aerror0("mpi support not built into this version of CSL");
  627. }
  628. static Lisp_Object MS_CDECL Lmpi_sendrecv(Lisp_Object nil, int nargs, ...)
  629. {
  630. CSL_IGNORE(nil);
  631. CSL_IGNORE(nargs);
  632. return aerror0("mpi support not built into this version of CSL");
  633. }
  634. static Lisp_Object MS_CDECL Lmpi_isend(Lisp_Object nil, int nargs, ...)
  635. {
  636. CSL_IGNORE(nil);
  637. CSL_IGNORE(nargs);
  638. return aerror0("mpi support not built into this version of CSL");
  639. }
  640. static Lisp_Object MS_CDECL Lmpi_irecv(Lisp_Object nil, int nargs, ...)
  641. {
  642. CSL_IGNORE(nil);
  643. CSL_IGNORE(nargs);
  644. return aerror0("mpi support not built into this version of CSL");
  645. }
  646. static Lisp_Object Lmpi_wait(Lisp_Object nil, Lisp_Object request)
  647. {
  648. CSL_IGNORE(nil);
  649. CSL_IGNORE(request);
  650. return aerror0("mpi support not built into this version of CSL");
  651. }
  652. static Lisp_Object Lmpi_test(Lisp_Object nil, Lisp_Object request)
  653. {
  654. CSL_IGNORE(nil);
  655. CSL_IGNORE(request);
  656. return aerror0("mpi support not built into this version of CSL");
  657. }
  658. static Lisp_Object MS_CDECL Lmpi_iprobe(Lisp_Object nil, int nargs, ...)
  659. {
  660. CSL_IGNORE(nil);
  661. CSL_IGNORE(nargs);
  662. return aerror0("mpi support not built into this version of CSL");
  663. }
  664. static Lisp_Object MS_CDECL Lmpi_probe(Lisp_Object nil, int nargs, ...)
  665. {
  666. CSL_IGNORE(nil);
  667. CSL_IGNORE(nargs);
  668. return aerror0("mpi support not built into this version of CSL");
  669. }
  670. static Lisp_Object Lmpi_barrier(Lisp_Object nil, Lisp_Object comm)
  671. {
  672. CSL_IGNORE(nil);
  673. CSL_IGNORE(comm);
  674. return aerror0("mpi support not built into this version of CSL");
  675. }
  676. static Lisp_Object MS_CDECL Lmpi_bcast(Lisp_Object nil, int nargs, ...)
  677. {
  678. CSL_IGNORE(nil);
  679. CSL_IGNORE(nargs);
  680. return aerror0("mpi support not built into this version of CSL");
  681. }
  682. static Lisp_Object MS_CDECL Lmpi_gather(Lisp_Object nil, int nargs, ...)
  683. {
  684. CSL_IGNORE(nil);
  685. CSL_IGNORE(nargs);
  686. return aerror0("mpi support not built into this version of CSL");
  687. }
  688. static Lisp_Object MS_CDECL Lmpi_scatter(Lisp_Object nil, int nargs, ...)
  689. {
  690. CSL_IGNORE(nil);
  691. CSL_IGNORE(nargs);
  692. return aerror0("mpi support not built into this version of CSL");
  693. }
  694. static Lisp_Object Lmpi_allgather(Lisp_Object nil,
  695. Lisp_Object message,
  696. Lisp_Object comm)
  697. {
  698. CSL_IGNORE(nil);
  699. CSL_IGNORE(message);
  700. CSL_IGNORE(comm);
  701. return aerror0("mpi support not built into this version of CSL");
  702. }
  703. static Lisp_Object Lmpi_alltoall(Lisp_Object nil,
  704. Lisp_Object smessages, Lisp_Object Lcomm)
  705. {
  706. CSL_IGNORE(nil);
  707. CSL_IGNORE(smessages);
  708. CSL_IGNORE(Lcomm);
  709. return aerror0("mpi support not built into this version of CSL");
  710. }
  711. #endif /* USE_MPI */
  712. setup_type const mpi_setup[] =
  713. {
  714. {"mpi_comm_rank", Lmpi_comm_rank, too_many_1, wrong_no_1},
  715. {"mpi_comm_size", Lmpi_comm_size, too_many_1, wrong_no_1},
  716. {"mpi_send", wrong_no_0a, wrong_no_0b, Lmpi_send},
  717. {"mpi_recv", wrong_no_0a, wrong_no_0b, Lmpi_recv},
  718. {"mpi_sendrecv", wrong_no_0a, wrong_no_0b, Lmpi_sendrecv},
  719. {"mpi_isend", wrong_no_0a, wrong_no_0b, Lmpi_isend},
  720. {"mpi_irecv", wrong_no_0a, wrong_no_0b, Lmpi_irecv},
  721. {"mpi_barrier", Lmpi_barrier, too_many_1, wrong_no_1},
  722. {"mpi_wait", Lmpi_wait, too_many_1, wrong_no_1},
  723. {"mpi_test", Lmpi_test, too_many_1, wrong_no_1},
  724. {"mpi_probe", wrong_no_0a, wrong_no_0b, Lmpi_probe},
  725. {"mpi_iprobe", wrong_no_0a, wrong_no_0b, Lmpi_iprobe},
  726. {"mpi_bcast", wrong_no_0a, wrong_no_0b, Lmpi_bcast},
  727. {"mpi_gather", wrong_no_0a, wrong_no_0b, Lmpi_gather},
  728. {"mpi_allgather", wrong_no_0a, Lmpi_allgather, wrong_no_2},
  729. {"mpi_scatter", wrong_no_0a, wrong_no_0b, Lmpi_scatter},
  730. {"mpi_alltoall", wrong_no_0a, Lmpi_alltoall, wrong_no_2},
  731. {NULL, 0, 0, 0}
  732. };
  733. /* end of cslmpi.c */