ruby-mpi 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -1,8 +1,12 @@
1
- = ruby-mpi
1
+ = Ruby-MPI
2
2
 
3
- Description goes here.
3
+ Ruby-MPI is a ruby binding of Message Passing Interface (MPI), which is an API specification that allows processes to communicate with one another by sending and receiving messages.
4
4
 
5
- == Contributing to ruby-mpi
5
+ == Install
6
+
7
+ # gem install ruby-mpi
8
+
9
+ == Contributing to Ruby-MPI
6
10
 
7
11
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
12
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/ext/mpi/mpi.c CHANGED
@@ -53,22 +53,43 @@ static VALUE cComm, cRequest, cOp, cErrhandler, cStatus;
53
53
  static VALUE eBUFFER, eCOUNT, eTYPE, eTAG, eCOMM, eRANK, eREQUEST, eROOT, eGROUP, eOP, eTOPOLOGY, eDIMS, eARG, eUNKNOWN, eTRUNCATE, eOTHER, eINTERN, eIN_STATUS, ePENDING, eACCESS, eAMODE, eASSERT, eBAD_FILE, eBASE, eCONVERSION, eDISP, eDUP_DATAREP, eFILE_EXISTS, eFILE_IN_USE, eFILE, eINFO_KEY, eINFO_NOKEY, eINFO_VALUE, eINFO, eIO, eKEYVAL, eLOCKTYPE, eNAME, eNO_MEM, eNOT_SAME, eNO_SPACE, eNO_SUCH_FILE, ePORT, eQUOTA, eREAD_ONLY, eRMA_CONFLICT, eRMA_SYNC, eSERVICE, eSIZE, eSPAWN, eUNSUPPORTED_DATAREP, eUNSUPPORTED_OPERATION, eWIN, eLASTCODE, eSYSRESOURCE;
54
54
 
55
55
  struct _Comm {
56
- MPI_Comm comm;
56
+ MPI_Comm Comm;
57
57
  };
58
58
  struct _Request {
59
- MPI_Request request;
59
+ MPI_Request Request;
60
60
  };
61
61
  struct _Op {
62
- MPI_Op op;
62
+ MPI_Op Op;
63
63
  };
64
64
  struct _Errhandler {
65
- MPI_Errhandler errhandler;
65
+ MPI_Errhandler Errhandler;
66
66
  };
67
67
 
68
68
  static bool _initialized = false;
69
69
  static bool _finalized = false;
70
70
 
71
71
 
72
+ #define DEF_FREE(name) \
73
+ static void \
74
+ name ## _free(void *ptr)\
75
+ {\
76
+ struct _ ## name *obj;\
77
+ obj = (struct _ ## name*) ptr;\
78
+ if (!_finalized)\
79
+ MPI_ ## name ## _free(&(obj->name)); \
80
+ free(obj);\
81
+ }
82
+ DEF_FREE(Comm)
83
+ DEF_FREE(Request)
84
+ DEF_FREE(Op)
85
+ DEF_FREE(Errhandler)
86
+ static void
87
+ Status_free(void *ptr)
88
+ {
89
+ free((MPI_Status*) ptr);
90
+ }
91
+
92
+
72
93
  #define CAE_ERR(type) case MPI_ERR_ ## type: rb_raise(e ## type,""); break
73
94
  static void
74
95
  check_error(int error)
@@ -129,19 +150,29 @@ check_error(int error)
129
150
  CAE_ERR(UNSUPPORTED_OPERATION);
130
151
  CAE_ERR(WIN);
131
152
  CAE_ERR(LASTCODE);
153
+ #ifdef MPI_ERR_SYSRESOURCE
132
154
  CAE_ERR(SYSRESOURCE);
155
+ #endif
133
156
  default:
134
157
  rb_raise(rb_eRuntimeError, "unknown error");
135
158
  }
136
159
  }
137
160
 
138
- #define DEF_CONST(st, v, const, name, klass) \
161
+ #define DEF_CONST(v, const, name) \
139
162
  {\
140
- v = ALLOC(struct st);\
163
+ v = ALLOC(struct _ ## v);\
141
164
  v->v = const;\
142
- rb_define_const(klass, #name, Data_Wrap_Struct(klass, 0, -1, v)); \
165
+ rb_define_const(c ## v, #name, Data_Wrap_Struct(c ## v, NULL, v ## _free, v)); \
143
166
  }
144
167
 
168
+ static void
169
+ _finalize()
170
+ {
171
+ if(_initialized && !_finalized) {
172
+ _finalized = true;
173
+ check_error(MPI_Finalize());
174
+ }
175
+ }
145
176
  static VALUE
146
177
  rb_m_init(int argc, VALUE *argv, VALUE self)
147
178
  {
@@ -151,11 +182,6 @@ rb_m_init(int argc, VALUE *argv, VALUE self)
151
182
  VALUE progname;
152
183
  int i;
153
184
 
154
- if (_initialized)
155
- return self;
156
- else
157
- _initialized = true;
158
-
159
185
  rb_scan_args(argc, argv, "01", &argary);
160
186
 
161
187
  if (NIL_P(argary)) {
@@ -178,45 +204,44 @@ rb_m_init(int argc, VALUE *argv, VALUE self)
178
204
  }
179
205
  cargc++;
180
206
 
181
- MPI_Init(&cargc, &cargv);
207
+ check_error(MPI_Init(&cargc, &cargv));
208
+ if (_initialized)
209
+ return self;
210
+ else
211
+ _initialized = true;
212
+ atexit(_finalize);
213
+
214
+
182
215
 
183
216
  // define MPI::Comm::WORLD
184
- struct _Comm *comm;
185
- DEF_CONST(_Comm, comm, MPI_COMM_WORLD, WORLD, cComm);
217
+ struct _Comm *Comm;
218
+ DEF_CONST(Comm, MPI_COMM_WORLD, WORLD);
186
219
  MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
187
220
 
188
221
  // define MPI::Op::???
189
- struct _Op *op;
190
- DEF_CONST(_Op, op, MPI_MAX, MAX, cOp);
191
- DEF_CONST(_Op, op, MPI_MIN, MIN, cOp);
192
- DEF_CONST(_Op, op, MPI_SUM, SUM, cOp);
193
- DEF_CONST(_Op, op, MPI_PROD, PROD, cOp);
194
- DEF_CONST(_Op, op, MPI_LAND, LAND, cOp);
195
- DEF_CONST(_Op, op, MPI_BAND, BAND, cOp);
196
- DEF_CONST(_Op, op, MPI_LOR, LOR, cOp);
197
- DEF_CONST(_Op, op, MPI_BOR, BOR, cOp);
198
- DEF_CONST(_Op, op, MPI_LXOR, LXOR, cOp);
199
- DEF_CONST(_Op, op, MPI_BXOR, BXOR, cOp);
200
- DEF_CONST(_Op, op, MPI_MAXLOC, MAXLOC, cOp);
201
- DEF_CONST(_Op, op, MPI_MINLOC, MINLOC, cOp);
202
- DEF_CONST(_Op, op, MPI_REPLACE, REPLACE, cOp);
222
+ struct _Op *Op;
223
+ DEF_CONST(Op, MPI_MAX, MAX);
224
+ DEF_CONST(Op, MPI_MIN, MIN);
225
+ DEF_CONST(Op, MPI_SUM, SUM);
226
+ DEF_CONST(Op, MPI_PROD, PROD);
227
+ DEF_CONST(Op, MPI_LAND, LAND);
228
+ DEF_CONST(Op, MPI_BAND, BAND);
229
+ DEF_CONST(Op, MPI_LOR, LOR);
230
+ DEF_CONST(Op, MPI_BOR, BOR);
231
+ DEF_CONST(Op, MPI_LXOR, LXOR);
232
+ DEF_CONST(Op, MPI_BXOR, BXOR);
233
+ DEF_CONST(Op, MPI_MAXLOC, MAXLOC);
234
+ DEF_CONST(Op, MPI_MINLOC, MINLOC);
235
+ DEF_CONST(Op, MPI_REPLACE, REPLACE);
203
236
 
204
237
  // define MPI::Errhandler::ERRORS_ARE_FATAL, ERRORS_RETURN
205
- struct _Errhandler *errhandler;
206
- DEF_CONST(_Errhandler, errhandler, MPI_ERRORS_ARE_FATAL, ERRORS_ARE_FATAL, cErrhandler);
207
- DEF_CONST(_Errhandler, errhandler, MPI_ERRORS_RETURN, ERRORS_RETURN, cErrhandler);
238
+ struct _Errhandler *Errhandler;
239
+ DEF_CONST(Errhandler, MPI_ERRORS_ARE_FATAL, ERRORS_ARE_FATAL);
240
+ DEF_CONST(Errhandler, MPI_ERRORS_RETURN, ERRORS_RETURN);
208
241
 
209
242
  return self;
210
243
  }
211
244
 
212
- static void
213
- _finalize()
214
- {
215
- if(_initialized && !_finalized) {
216
- _finalized = true;
217
- check_error(MPI_Finalize());
218
- }
219
- }
220
245
  static VALUE
221
246
  rb_m_finalize(VALUE self)
222
247
  {
@@ -230,7 +255,7 @@ static VALUE
230
255
  rb_comm_alloc(VALUE klass)
231
256
  {
232
257
  struct _Comm *ptr = ALLOC(struct _Comm);
233
- return Data_Wrap_Struct(klass, 0, -1, ptr);
258
+ return Data_Wrap_Struct(klass, NULL, Comm_free, ptr);
234
259
  }
235
260
  static VALUE
236
261
  rb_comm_initialize(VALUE self)
@@ -244,7 +269,7 @@ rb_comm_size(VALUE self)
244
269
  struct _Comm *comm;
245
270
  int size;
246
271
  Data_Get_Struct(self, struct _Comm, comm);
247
- check_error(MPI_Comm_size(comm->comm, &size));
272
+ check_error(MPI_Comm_size(comm->Comm, &size));
248
273
  return INT2NUM(size);
249
274
  }
250
275
  static VALUE
@@ -253,7 +278,7 @@ rb_comm_rank(VALUE self)
253
278
  struct _Comm *comm;
254
279
  int rank;
255
280
  Data_Get_Struct(self, struct _Comm, comm);
256
- check_error(MPI_Comm_rank(comm->comm, &rank));
281
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
257
282
  return INT2NUM(rank);
258
283
  }
259
284
  static VALUE
@@ -268,7 +293,7 @@ rb_comm_send(VALUE self, VALUE rb_obj, VALUE rb_dest, VALUE rb_tag)
268
293
  dest = NUM2INT(rb_dest);
269
294
  tag = NUM2INT(rb_tag);
270
295
  Data_Get_Struct(self, struct _Comm, comm);
271
- check_error(MPI_Send(buffer, len, type, dest, tag, comm->comm));
296
+ check_error(MPI_Send(buffer, len, type, dest, tag, comm->Comm));
272
297
 
273
298
  return Qnil;
274
299
  }
@@ -286,8 +311,8 @@ rb_comm_isend(VALUE self, VALUE rb_obj, VALUE rb_dest, VALUE rb_tag)
286
311
  dest = NUM2INT(rb_dest);
287
312
  tag = NUM2INT(rb_tag);
288
313
  Data_Get_Struct(self, struct _Comm, comm);
289
- rb_request = Data_Make_Struct(cRequest, struct _Request, 0, -1, request);
290
- check_error(MPI_Isend(buffer, len, type, dest, tag, comm->comm, &(request->request)));
314
+ rb_request = Data_Make_Struct(cRequest, struct _Request, NULL, Request_free, request);
315
+ check_error(MPI_Isend(buffer, len, type, dest, tag, comm->Comm, &(request->Request)));
291
316
 
292
317
  return rb_request;
293
318
  }
@@ -306,9 +331,9 @@ rb_comm_recv(VALUE self, VALUE rb_obj, VALUE rb_source, VALUE rb_tag)
306
331
 
307
332
  Data_Get_Struct(self, struct _Comm, comm);
308
333
  status = ALLOC(MPI_Status);
309
- check_error(MPI_Recv(buffer, len, type, source, tag, comm->comm, status));
334
+ check_error(MPI_Recv(buffer, len, type, source, tag, comm->Comm, status));
310
335
 
311
- return Data_Wrap_Struct(cStatus, 0, -1, status);
336
+ return Data_Wrap_Struct(cStatus, NULL, Status_free, status);
312
337
  }
313
338
  static VALUE
314
339
  rb_comm_irecv(VALUE self, VALUE rb_obj, VALUE rb_source, VALUE rb_tag)
@@ -324,8 +349,8 @@ rb_comm_irecv(VALUE self, VALUE rb_obj, VALUE rb_source, VALUE rb_tag)
324
349
  source = NUM2INT(rb_source);
325
350
  tag = NUM2INT(rb_tag);
326
351
  Data_Get_Struct(self, struct _Comm, comm);
327
- rb_request = Data_Make_Struct(cRequest, struct _Request, 0, -1, request);
328
- check_error(MPI_Irecv(buffer, len, type, source, tag, comm->comm, &(request->request)));
352
+ rb_request = Data_Make_Struct(cRequest, struct _Request, NULL, Request_free, request);
353
+ check_error(MPI_Irecv(buffer, len, type, source, tag, comm->Comm, &(request->Request)));
329
354
 
330
355
  return rb_request;
331
356
  }
@@ -340,15 +365,15 @@ rb_comm_gather(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_root)
340
365
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
341
366
  root = NUM2INT(rb_root);
342
367
  Data_Get_Struct(self, struct _Comm, comm);
343
- check_error(MPI_Comm_rank(comm->comm, &rank));
344
- check_error(MPI_Comm_size(comm->comm, &size));
368
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
369
+ check_error(MPI_Comm_size(comm->Comm, &size));
345
370
  if (rank == root) {
346
371
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
347
372
  if (recvcount < sendcount*size)
348
373
  rb_raise(rb_eArgError, "recvbuf is too small");
349
374
  recvcount = sendcount;
350
375
  }
351
- check_error(MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm->comm));
376
+ check_error(MPI_Gather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm->Comm));
352
377
  return Qnil;
353
378
  }
354
379
  static VALUE
@@ -361,13 +386,13 @@ rb_comm_allgather(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf)
361
386
  struct _Comm *comm;
362
387
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
363
388
  Data_Get_Struct(self, struct _Comm, comm);
364
- check_error(MPI_Comm_rank(comm->comm, &rank));
365
- check_error(MPI_Comm_size(comm->comm, &size));
389
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
390
+ check_error(MPI_Comm_size(comm->Comm, &size));
366
391
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
367
392
  if (recvcount < sendcount*size)
368
393
  rb_raise(rb_eArgError, "recvbuf is too small");
369
394
  recvcount = sendcount;
370
- check_error(MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm->comm));
395
+ check_error(MPI_Allgather(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm->Comm));
371
396
  return Qnil;
372
397
  }
373
398
  static VALUE
@@ -381,7 +406,7 @@ rb_comm_bcast(VALUE self, VALUE rb_buffer, VALUE rb_root)
381
406
  OBJ2C(rb_buffer, count, buffer, type);
382
407
  root = NUM2INT(rb_root);
383
408
  Data_Get_Struct(self, struct _Comm, comm);
384
- check_error(MPI_Bcast(buffer, count, type, root, comm->comm));
409
+ check_error(MPI_Bcast(buffer, count, type, root, comm->Comm));
385
410
  return Qnil;
386
411
  }
387
412
  static VALUE
@@ -395,35 +420,57 @@ rb_comm_scatter(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_root)
395
420
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
396
421
  root = NUM2INT(rb_root);
397
422
  Data_Get_Struct(self, struct _Comm, comm);
398
- check_error(MPI_Comm_rank(comm->comm, &rank));
399
- check_error(MPI_Comm_size(comm->comm, &size));
423
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
424
+ check_error(MPI_Comm_size(comm->Comm, &size));
400
425
  if (rank == root) {
401
426
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
402
427
  if (sendcount > recvcount*size)
403
428
  rb_raise(rb_eArgError, "recvbuf is too small");
404
429
  sendcount = recvcount;
405
430
  }
406
- check_error(MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm->comm));
431
+ check_error(MPI_Scatter(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm->Comm));
407
432
  return Qnil;
408
433
  }
409
434
  static VALUE
435
+ rb_comm_sendrecv(VALUE self, VALUE rb_sendbuf, VALUE rb_dest, VALUE rb_sendtag, VALUE rb_recvbuf, VALUE rb_source, VALUE rb_recvtag)
436
+ {
437
+ void *sendbuf, *recvbuf;
438
+ int sendcount, recvcount;
439
+ MPI_Datatype sendtype, recvtype;
440
+ int dest, source;
441
+ int sendtag, recvtag;
442
+ int size;
443
+ struct _Comm *comm;
444
+ MPI_Status *status;
445
+ OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
446
+ Data_Get_Struct(self, struct _Comm, comm);
447
+ check_error(MPI_Comm_size(comm->Comm, &size));
448
+ OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
449
+ dest = NUM2INT(rb_dest);
450
+ source = NUM2INT(rb_source);
451
+ sendtag = NUM2INT(rb_sendtag);
452
+ recvtag = NUM2INT(rb_recvtag);
453
+ status = ALLOC(MPI_Status);
454
+ check_error(MPI_Sendrecv(sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm->Comm, status));
455
+ return Data_Wrap_Struct(cStatus, NULL, Status_free, status);
456
+ }
457
+ static VALUE
410
458
  rb_comm_alltoall(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf)
411
459
  {
412
460
  void *sendbuf, *recvbuf;
413
461
  int sendcount, recvcount;
414
462
  MPI_Datatype sendtype, recvtype;
415
- int rank, size;
463
+ int size;
416
464
  struct _Comm *comm;
417
465
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
418
466
  Data_Get_Struct(self, struct _Comm, comm);
419
- check_error(MPI_Comm_rank(comm->comm, &rank));
420
- check_error(MPI_Comm_size(comm->comm, &size));
467
+ check_error(MPI_Comm_size(comm->Comm, &size));
421
468
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
422
469
  if (recvcount < sendcount)
423
470
  rb_raise(rb_eArgError, "recvbuf is too small");
424
471
  recvcount = recvcount/size;
425
472
  sendcount = sendcount/size;
426
- check_error(MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm->comm));
473
+ check_error(MPI_Alltoall(sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm->Comm));
427
474
  return Qnil;
428
475
  }
429
476
  static VALUE
@@ -438,8 +485,8 @@ rb_comm_reduce(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_op, VALU
438
485
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
439
486
  root = NUM2INT(rb_root);
440
487
  Data_Get_Struct(self, struct _Comm, comm);
441
- check_error(MPI_Comm_rank(comm->comm, &rank));
442
- check_error(MPI_Comm_size(comm->comm, &size));
488
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
489
+ check_error(MPI_Comm_size(comm->Comm, &size));
443
490
  if (rank == root) {
444
491
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
445
492
  if (recvcount != sendcount)
@@ -448,7 +495,7 @@ rb_comm_reduce(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_op, VALU
448
495
  rb_raise(rb_eArgError, "sendbuf and recvbuf has the same type");
449
496
  }
450
497
  Data_Get_Struct(rb_op, struct _Op, op);
451
- check_error(MPI_Reduce(sendbuf, recvbuf, sendcount, sendtype, op->op, root, comm->comm));
498
+ check_error(MPI_Reduce(sendbuf, recvbuf, sendcount, sendtype, op->Op, root, comm->Comm));
452
499
  return Qnil;
453
500
  }
454
501
  static VALUE
@@ -462,15 +509,15 @@ rb_comm_allreduce(VALUE self, VALUE rb_sendbuf, VALUE rb_recvbuf, VALUE rb_op)
462
509
  struct _Op *op;
463
510
  OBJ2C(rb_sendbuf, sendcount, sendbuf, sendtype);
464
511
  Data_Get_Struct(self, struct _Comm, comm);
465
- check_error(MPI_Comm_rank(comm->comm, &rank));
466
- check_error(MPI_Comm_size(comm->comm, &size));
512
+ check_error(MPI_Comm_rank(comm->Comm, &rank));
513
+ check_error(MPI_Comm_size(comm->Comm, &size));
467
514
  OBJ2C(rb_recvbuf, recvcount, recvbuf, recvtype);
468
515
  if (recvcount != sendcount)
469
516
  rb_raise(rb_eArgError, "sendbuf and recvbuf has the same length");
470
517
  if (recvtype != sendtype)
471
518
  rb_raise(rb_eArgError, "sendbuf and recvbuf has the same type");
472
519
  Data_Get_Struct(rb_op, struct _Op, op);
473
- check_error(MPI_Allreduce(sendbuf, recvbuf, recvcount, recvtype, op->op, comm->comm));
520
+ check_error(MPI_Allreduce(sendbuf, recvbuf, recvcount, recvtype, op->Op, comm->Comm));
474
521
  return Qnil;
475
522
  }
476
523
  static VALUE
@@ -481,8 +528,8 @@ rb_comm_get_Errhandler(VALUE self)
481
528
  VALUE rb_errhandler;
482
529
 
483
530
  Data_Get_Struct(self, struct _Comm, comm);
484
- rb_errhandler = Data_Make_Struct(cErrhandler, struct _Errhandler, 0, -1, errhandler);
485
- MPI_Comm_get_errhandler(comm->comm, &(errhandler->errhandler));
531
+ rb_errhandler = Data_Make_Struct(cErrhandler, struct _Errhandler, NULL, Errhandler_free, errhandler);
532
+ MPI_Comm_get_errhandler(comm->Comm, &(errhandler->Errhandler));
486
533
  return rb_errhandler;
487
534
  }
488
535
  static VALUE
@@ -493,7 +540,15 @@ rb_comm_set_Errhandler(VALUE self, VALUE rb_errhandler)
493
540
 
494
541
  Data_Get_Struct(self, struct _Comm, comm);
495
542
  Data_Get_Struct(rb_errhandler, struct _Errhandler, errhandler);
496
- MPI_Comm_set_errhandler(comm->comm, errhandler->errhandler);
543
+ MPI_Comm_set_errhandler(comm->Comm, errhandler->Errhandler);
544
+ return self;
545
+ }
546
+ static VALUE
547
+ rb_comm_barrier(VALUE self)
548
+ {
549
+ struct _Comm *comm;
550
+ Data_Get_Struct(self, struct _Comm, comm);
551
+ check_error(MPI_Barrier(comm->Comm));
497
552
  return self;
498
553
  }
499
554
 
@@ -505,8 +560,8 @@ rb_request_wait(VALUE self)
505
560
  struct _Request *request;
506
561
  Data_Get_Struct(self, struct _Request, request);
507
562
  status = ALLOC(MPI_Status);
508
- check_error(MPI_Wait(&(request->request), status));
509
- return Data_Wrap_Struct(cStatus, 0, -1, status);
563
+ check_error(MPI_Wait(&(request->Request), status));
564
+ return Data_Wrap_Struct(cStatus, NULL, Status_free, status);
510
565
  }
511
566
 
512
567
  // MPI::Errhandler
@@ -516,7 +571,7 @@ rb_errhandler_eql(VALUE self, VALUE other)
516
571
  struct _Errhandler *eh0, *eh1;
517
572
  Data_Get_Struct(self, struct _Errhandler, eh0);
518
573
  Data_Get_Struct(other, struct _Errhandler, eh1);
519
- return eh0->errhandler == eh1->errhandler ? Qtrue : Qfalse;
574
+ return eh0->Errhandler == eh1->Errhandler ? Qtrue : Qfalse;
520
575
  }
521
576
 
522
577
  // MPI::Status
@@ -548,8 +603,6 @@ void Init_mpi()
548
603
 
549
604
  rb_require("narray");
550
605
 
551
- atexit(_finalize);
552
-
553
606
  // MPI
554
607
  mMPI = rb_define_module("MPI");
555
608
  rb_define_module_function(mMPI, "Init", rb_m_init, -1);
@@ -557,6 +610,7 @@ void Init_mpi()
557
610
  rb_define_const(mMPI, "VERSION", INT2NUM(MPI_VERSION));
558
611
  rb_define_const(mMPI, "SUBVERSION", INT2NUM(MPI_SUBVERSION));
559
612
  rb_define_const(mMPI, "SUCCESS", INT2NUM(MPI_SUCCESS));
613
+ rb_define_const(mMPI, "PROC_NULL", INT2NUM(MPI_PROC_NULL));
560
614
 
561
615
  // MPI::Comm
562
616
  cComm = rb_define_class_under(mMPI, "Comm", rb_cObject);
@@ -572,11 +626,13 @@ void Init_mpi()
572
626
  rb_define_method(cComm, "Allgather", rb_comm_allgather, 2);
573
627
  rb_define_method(cComm, "Bcast", rb_comm_bcast, 2);
574
628
  rb_define_method(cComm, "Scatter", rb_comm_scatter, 3);
629
+ rb_define_method(cComm, "Sendrecv", rb_comm_sendrecv, 6);
575
630
  rb_define_method(cComm, "Alltoall", rb_comm_alltoall, 2);
576
631
  rb_define_method(cComm, "Reduce", rb_comm_reduce, 4);
577
632
  rb_define_method(cComm, "Allreduce", rb_comm_allreduce, 3);
578
633
  rb_define_method(cComm, "Errhandler", rb_comm_get_Errhandler, 0);
579
634
  rb_define_method(cComm, "Errhandler=", rb_comm_set_Errhandler, 1);
635
+ rb_define_method(cComm, "Barrier", rb_comm_barrier, 0);
580
636
 
581
637
  // MPI::Request
582
638
  cRequest = rb_define_class_under(mMPI, "Request", rb_cObject);
data/ruby-mpi.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby-mpi}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Seiya Nishizawa"]
12
- s.date = %q{2011-04-21}
12
+ s.date = %q{2011-04-22}
13
13
  s.description = %q{A ruby binding of Message Passing Interface (MPI), which is an API specification that allows processes to communicate with one another by sending and receiving messages.}
14
14
  s.email = %q{seiya@gfd-dennou.org}
15
15
  s.extensions = ["ext/mpi/extconf.rb"]
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
38
38
  s.homepage = %q{http://github.com/seiya/ruby-mpi}
39
39
  s.licenses = ["MIT"]
40
40
  s.require_paths = ["lib"]
41
- s.rubygems_version = %q{1.3.7}
41
+ s.rubygems_version = %q{1.7.2}
42
42
  s.summary = %q{A ruby binding of MPI}
43
43
  s.test_files = [
44
44
  "spec/ruby-mpi_spec.rb",
@@ -46,7 +46,6 @@ Gem::Specification.new do |s|
46
46
  ]
47
47
 
48
48
  if s.respond_to? :specification_version then
49
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
49
  s.specification_version = 3
51
50
 
52
51
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -8,49 +8,49 @@ describe "MPI" do
8
8
  MPI.Finalize()
9
9
  end
10
10
 
11
+ before do
12
+ @world = MPI::Comm::WORLD
13
+ end
14
+
11
15
  it "should give version" do
12
- MPI.constants.should include("VERSION")
13
- MPI.constants.should include("SUBVERSION")
14
16
  MPI::VERSION.class.should eql(Fixnum)
15
17
  MPI::SUBVERSION.class.should eql(Fixnum)
16
18
  end
17
19
 
18
- it "should have Comm:WORLD" do
19
- MPI::Comm.constants.should include("WORLD")
20
- world = MPI::Comm::WORLD
21
- world.rank.class.should eql(Fixnum)
22
- world.size.class.should eql(Fixnum)
23
- world.size.should > 0
20
+ it "should give rank and size" do
21
+ @world.rank.class.should eql(Fixnum)
22
+ @world.size.class.should eql(Fixnum)
23
+ @world.size.should > 0
24
24
  end
25
25
 
26
26
  it "should send and receive String" do
27
- world = MPI::Comm::WORLD
28
- message = "Hello from #{world.rank}"
27
+ rank = @world.rank
28
+ message = "Hello from #{rank}"
29
29
  tag = 0
30
- world.Send(message, 0, tag)
31
- if world.rank == 0
32
- world.size.times do |i|
33
- str = " "*30
34
- status = world.Recv(str, i, tag)
35
- status.source.should eql(i)
30
+ @world.Send(message, 0, tag) if rank != 0
31
+ if rank == 0
32
+ (@world.size-1).times do |i|
33
+ str = " "*"Hello from #{i+1}".length
34
+ status = @world.Recv(str, i+1, tag)
35
+ status.source.should eql(i+1)
36
36
  status.tag.should eql(tag)
37
37
  status.error.should eq(MPI::SUCCESS)
38
- str.should match(/\AHello from #{i}+/)
38
+ str.should match(/\AHello from #{i+1}/)
39
39
  end
40
40
  end
41
41
  end
42
42
 
43
43
  it "should send and receive NArray" do
44
- world = MPI::Comm::WORLD
45
44
  tag = 0
45
+ rank = @world.rank
46
46
  [NArray[1,2,3], NArray[3.0,2.0,1.0]].each do |ary0|
47
47
  ary0 = NArray[1,2,3]
48
- world.Send(ary0, 0, tag)
49
- if world.rank == 0
50
- world.size.times do |i|
48
+ @world.Send(ary0, 0, tag) if rank != 0
49
+ if rank == 0
50
+ (@world.size-1).times do |i|
51
51
  ary1 = NArray.new(ary0.typecode, ary0.total)
52
- status = world.Recv(ary1, i, tag)
53
- status.source.should eql(i)
52
+ status = @world.Recv(ary1, i+1, tag)
53
+ status.source.should eql(i+1)
54
54
  status.tag.should eql(tag)
55
55
  status.error.should eq(MPI::SUCCESS)
56
56
  ary1.should == ary0
@@ -60,34 +60,35 @@ describe "MPI" do
60
60
  end
61
61
 
62
62
  it "should send and receive without blocking" do
63
- world = MPI::Comm::WORLD
64
- message = "Hello from #{world.rank}"
65
63
  tag = 0
66
- request = world.Isend(message, 0, tag)
67
- status = request.Wait
68
- status.source.should eql(world.rank)
69
- status.tag.should eql(tag)
70
- if world.rank == 0
71
- world.size.times do |i|
72
- str = " "*30
73
- request = world.Irecv(str, i, tag)
74
- status = request.Wait
75
- status.source.should eql(i)
64
+ rank = @world.rank
65
+ message = "Hello from #{rank}"
66
+ if rank != 0
67
+ request = @world.Isend(message, 0, tag)
68
+ status = request.Wait
69
+ # status.source.should eql(rank)
70
+ status.tag.should eql(tag)
71
+ end
72
+ if rank == 0
73
+ (@world.size-1).times do |i|
74
+ str = " "*"Hello from #{i+1}".length
75
+ request_recv = @world.Irecv(str, i+1, tag)
76
+ status = request_recv.Wait
77
+ status.source.should eql(i+1)
76
78
  status.tag.should eql(tag)
77
- str.should match(/\AHello from #{i}+/)
79
+ str.should match(/\AHello from #{i+1}/)
78
80
  end
79
81
  end
80
82
  end
81
83
 
82
84
  it "should gather data" do
83
- world = MPI::Comm::WORLD
84
- rank = world.rank
85
- size = world.size
85
+ rank = @world.rank
86
+ size = @world.size
86
87
  root = 0
87
88
  bufsize = 2
88
89
  sendbuf = rank.to_s*bufsize
89
90
  recvbuf = rank == root ? "?"*bufsize*size : nil
90
- world.Gather(sendbuf, recvbuf, root)
91
+ @world.Gather(sendbuf, recvbuf, root)
91
92
  if rank == root
92
93
  str = ""
93
94
  size.times{|i| str << i.to_s*bufsize}
@@ -96,21 +97,19 @@ describe "MPI" do
96
97
  end
97
98
 
98
99
  it "should gather data to all processes (allgather)" do
99
- world = MPI::Comm::WORLD
100
- rank = world.rank
101
- size = world.size
100
+ rank = @world.rank
101
+ size = @world.size
102
102
  bufsize = 2
103
103
  sendbuf = rank.to_s*bufsize
104
104
  recvbuf = "?"*bufsize*size
105
- world.Allgather(sendbuf, recvbuf)
105
+ @world.Allgather(sendbuf, recvbuf)
106
106
  str = ""
107
107
  size.times{|i| str << i.to_s*bufsize}
108
108
  recvbuf.should eql(str)
109
109
  end
110
110
 
111
111
  it "should broad cast data (bcast)" do
112
- world = MPI::Comm::WORLD
113
- rank = world.rank
112
+ rank = @world.rank
114
113
  root = 0
115
114
  bufsize = 2
116
115
  if rank == root
@@ -118,14 +117,13 @@ describe "MPI" do
118
117
  else
119
118
  buffer = " "*bufsize
120
119
  end
121
- world.Bcast(buffer, root)
120
+ @world.Bcast(buffer, root)
122
121
  buffer.should eql(root.to_s*bufsize)
123
122
  end
124
123
 
125
124
  it "should scatter data" do
126
- world = MPI::Comm::WORLD
127
- rank = world.rank
128
- size = world.size
125
+ rank = @world.rank
126
+ size = @world.size
129
127
  root = 0
130
128
  bufsize = 2
131
129
  if rank == root
@@ -135,32 +133,50 @@ describe "MPI" do
135
133
  sendbuf = nil
136
134
  end
137
135
  recvbuf = " "*bufsize
138
- world.Scatter(sendbuf, recvbuf, root)
136
+ @world.Scatter(sendbuf, recvbuf, root)
139
137
  recvbuf.should eql(rank.to_s*bufsize)
140
138
  end
141
139
 
140
+ it "should send and recv data (sendrecv)" do
141
+ rank = @world.rank
142
+ size = @world.size
143
+ dest = rank-1
144
+ dest = size-1 if dest < 0
145
+ #dest = MPI::PROC_NULL if dest < 0
146
+ source = rank+1
147
+ source = 0 if source > size-1
148
+ #source = MPI::PROC_NULL if source > size-1
149
+ sendtag = rank
150
+ recvtag = source
151
+ bufsize = 2
152
+ sendbuf = rank.to_s*bufsize
153
+ recvbuf = " "*bufsize
154
+ @world.Sendrecv(sendbuf, dest, sendtag, recvbuf, source, recvtag);
155
+ if source != MPI::PROC_NULL
156
+ recvbuf.should eql(source.to_s*bufsize)
157
+ end
158
+ end
159
+
142
160
  it "should change data between each others (alltoall)" do
143
- world = MPI::Comm::WORLD
144
- rank = world.rank
145
- size = world.size
161
+ rank = @world.rank
162
+ size = @world.size
146
163
  bufsize = 2
147
164
  sendbuf = rank.to_s*bufsize*size
148
165
  recvbuf = "?"*bufsize*size
149
- world.Alltoall(sendbuf, recvbuf)
166
+ @world.Alltoall(sendbuf, recvbuf)
150
167
  str = ""
151
168
  size.times{|i| str << i.to_s*bufsize}
152
169
  recvbuf.should eql(str)
153
170
  end
154
171
 
155
172
  it "should reduce data" do
156
- world = MPI::Comm::WORLD
157
- rank = world.rank
158
- size = world.size
173
+ rank = @world.rank
174
+ size = @world.size
159
175
  root = 0
160
176
  bufsize = 2
161
177
  sendbuf = NArray.to_na([rank]*bufsize)
162
178
  recvbuf = rank == root ? NArray.new(sendbuf.typecode,bufsize) : nil
163
- world.Reduce(sendbuf, recvbuf, MPI::Op::SUM, root)
179
+ @world.Reduce(sendbuf, recvbuf, MPI::Op::SUM, root)
164
180
  if rank == root
165
181
  ary = NArray.new(sendbuf.typecode,bufsize).fill(size*(size-1)/2.0)
166
182
  recvbuf.should == ary
@@ -168,25 +184,24 @@ describe "MPI" do
168
184
  end
169
185
 
170
186
  it "should reduce data and send to all processes (allreduce)" do
171
- world = MPI::Comm::WORLD
172
- rank = world.rank
173
- size = world.size
187
+ rank = @world.rank
188
+ size = @world.size
174
189
  bufsize = 2
175
190
  sendbuf = NArray.to_na([rank]*bufsize)
176
191
  recvbuf = NArray.new(sendbuf.typecode,bufsize)
177
- world.Allreduce(sendbuf, recvbuf, MPI::Op::SUM)
192
+ @world.Allreduce(sendbuf, recvbuf, MPI::Op::SUM)
178
193
  ary = NArray.new(sendbuf.typecode,bufsize).fill(size*(size-1)/2.0)
179
194
  recvbuf.should == ary
180
195
  end
181
196
 
182
-
197
+ it "should not raise exception in calling barrier" do
198
+ @world.Barrier
199
+ end
183
200
 
184
201
 
185
202
  it "shoud raise exeption" do
186
- world = MPI::Comm::WORLD
187
- lambda{ world.Send("", -1, 0) }.should raise_error(MPI::ERR::RANK)
188
- lambda{ world.Send("", world.size+1, 0) }.should raise_error(MPI::ERR::RANK)
189
- world.Errhandler.should eql(MPI::Errhandler::ERRORS_RETURN)
203
+ lambda{ @world.Send("", @world.size+1, 0) }.should raise_error(MPI::ERR::RANK)
204
+ @world.Errhandler.should eql(MPI::Errhandler::ERRORS_RETURN)
190
205
  end
191
206
 
192
207
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-mpi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 1
9
- - 0
10
- version: 0.1.0
4
+ prerelease:
5
+ version: 0.2.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Seiya Nishizawa
@@ -15,85 +10,63 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-04-21 00:00:00 +09:00
19
- default_executable:
13
+ date: 2011-04-22 00:00:00 Z
20
14
  dependencies:
21
15
  - !ruby/object:Gem::Dependency
22
- prerelease: false
23
16
  name: rspec
24
- version_requirements: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &id001 !ruby/object:Gem::Requirement
25
18
  none: false
26
19
  requirements:
27
20
  - - ~>
28
21
  - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 2
32
- - 3
33
- - 0
34
22
  version: 2.3.0
35
- requirement: *id001
36
23
  type: :development
37
- - !ruby/object:Gem::Dependency
38
24
  prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
39
27
  name: bundler
40
- version_requirements: &id002 !ruby/object:Gem::Requirement
28
+ requirement: &id002 !ruby/object:Gem::Requirement
41
29
  none: false
42
30
  requirements:
43
31
  - - ~>
44
32
  - !ruby/object:Gem::Version
45
- hash: 23
46
- segments:
47
- - 1
48
- - 0
49
- - 0
50
33
  version: 1.0.0
51
- requirement: *id002
52
34
  type: :development
53
- - !ruby/object:Gem::Dependency
54
35
  prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
55
38
  name: jeweler
56
- version_requirements: &id003 !ruby/object:Gem::Requirement
39
+ requirement: &id003 !ruby/object:Gem::Requirement
57
40
  none: false
58
41
  requirements:
59
42
  - - ~>
60
43
  - !ruby/object:Gem::Version
61
- hash: 7
62
- segments:
63
- - 1
64
- - 5
65
- - 2
66
44
  version: 1.5.2
67
- requirement: *id003
68
45
  type: :development
69
- - !ruby/object:Gem::Dependency
70
46
  prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
71
49
  name: rcov
72
- version_requirements: &id004 !ruby/object:Gem::Requirement
50
+ requirement: &id004 !ruby/object:Gem::Requirement
73
51
  none: false
74
52
  requirements:
75
53
  - - ">="
76
54
  - !ruby/object:Gem::Version
77
- hash: 3
78
- segments:
79
- - 0
80
55
  version: "0"
81
- requirement: *id004
82
56
  type: :development
83
- - !ruby/object:Gem::Dependency
84
57
  prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
85
60
  name: narray
86
- version_requirements: &id005 !ruby/object:Gem::Requirement
61
+ requirement: &id005 !ruby/object:Gem::Requirement
87
62
  none: false
88
63
  requirements:
89
64
  - - ">="
90
65
  - !ruby/object:Gem::Version
91
- hash: 3
92
- segments:
93
- - 0
94
66
  version: "0"
95
- requirement: *id005
96
67
  type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
97
70
  description: A ruby binding of Message Passing Interface (MPI), which is an API specification that allows processes to communicate with one another by sending and receiving messages.
98
71
  email: seiya@gfd-dennou.org
99
72
  executables: []
@@ -120,7 +93,6 @@ files:
120
93
  - samples/narray.rb
121
94
  - spec/ruby-mpi_spec.rb
122
95
  - spec/spec_helper.rb
123
- has_rdoc: true
124
96
  homepage: http://github.com/seiya/ruby-mpi
125
97
  licenses:
126
98
  - MIT
@@ -134,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
106
  requirements:
135
107
  - - ">="
136
108
  - !ruby/object:Gem::Version
137
- hash: 3
109
+ hash: -3549605766415082841
138
110
  segments:
139
111
  - 0
140
112
  version: "0"
@@ -143,14 +115,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
115
  requirements:
144
116
  - - ">="
145
117
  - !ruby/object:Gem::Version
146
- hash: 3
147
- segments:
148
- - 0
149
118
  version: "0"
150
119
  requirements: []
151
120
 
152
121
  rubyforge_project:
153
- rubygems_version: 1.3.7
122
+ rubygems_version: 1.7.2
154
123
  signing_key:
155
124
  specification_version: 3
156
125
  summary: A ruby binding of MPI