mpipe 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 638f1385e64bf50aedff83fbdec7cf8de6f2e63b
4
- data.tar.gz: e16b54cc652d0f6503cd4776bf716903fcaf2703
3
+ metadata.gz: e4f0bec53a0a6940093b513532384491708117c9
4
+ data.tar.gz: 9f15045ca9c5e95c21cb60903d95f3fb16191525
5
5
  SHA512:
6
- metadata.gz: df234ecdd079cb9b24f7afb9c8c1f8ce585cd247f6286a4c49e8484b5b7296ec2445ffb3cf603d5a2ef69be8dd567b6c8a03905f6c0d3a96b793869c76e2839f
7
- data.tar.gz: 5872d1e9ab4b7536d50d55a9cb778a9d43cc140b81e6bdaed70388b19af051956039e03554338ee11399a8f56af39c40c10a9130f0e2bdca67deb0acc9172d7a
6
+ metadata.gz: 50908b6ec00bc10bcef427998eb7f2941bbc1d6d2aadd33cb928e6a1aa37770bdf31663ca027fd8690ba259a4429d6f2336b3fa124e139c123ff4bb4c5ddcdd4
7
+ data.tar.gz: 3a06ab215c22444df2914fd583aeebb4aab9138ad68affb090c5949119a41063b006c5d76fdd7b82d5f5704fb7ba31236b0f3264cee41feb67ca66384f5c0e07
data/.gitignore CHANGED
@@ -47,3 +47,4 @@ TAGS
47
47
  t.rb
48
48
  *.bak[0-9]
49
49
  bak
50
+ ext/mpipe/Makefile
data/README.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  Ruby's IO.pipe emulation over MPI
4
4
 
5
+ [GitHub](https://github.com/masa16/mpipe) | [RubyGems](https://rubygems.org/gems/mpipe)
6
+
7
+ ## Requirement
8
+
9
+ Message Passing Interface (MPI) framework such as
10
+ [OpenMPI](https://www.open-mpi.org/), [MPICH](https://www.mpich.org/), etc.
11
+
12
+ Commands:
13
+ * mpicc - Compiler for MPI programs.
14
+ * mpirun - Command to run MPI program.
15
+
5
16
  ## Installation
6
17
 
7
18
  Add this line to your application's Gemfile:
@@ -66,11 +77,11 @@ MPipe::Comm.size -- calls MPI_Comm_size(), return the size of this environment.
66
77
 
67
78
  mp = MPipe.new(rank) -- returns pipe to MPI process with rank.
68
79
  mp.write(str) -- emulate IO#write.
69
- mp.read(maxlen,outbuf) -- emulate IO#read.
70
- mp.read_nonblock(maxlen,outbuf) -- emulate IO#read_nonblock.
80
+ mp.read(length,outbuf=nil) -- emulate IO#read.
81
+ mp.read_nonblock(maxlen,outbuf=nil,excepton:true) -- emulate IO#read_nonblock.
71
82
  MPipe.select(array_of_mpipe) -- emulate IO.select
72
83
  ```
73
84
 
74
85
  ## Contributing
75
86
 
76
- Bug reports and pull requests are welcome on GitHub at https://github.com/Masahiro TANAKA/mpipe.
87
+ Bug reports and pull requests are welcome on GitHub at https://github.com/masa16/mpipe.
data/ext/mpipe/mpipe.c CHANGED
@@ -3,7 +3,7 @@
3
3
  //#include "ruby/encoding.h"
4
4
  #include "mpi.h"
5
5
 
6
- #define MPIPE_VERSION "0.1.0"
6
+ #define MPIPE_VERSION "0.2.0"
7
7
 
8
8
  static int mp_buffer_size = 4098;
9
9
  static int mp_initialized = 0;
@@ -207,7 +207,13 @@ mp_s_allocate(VALUE klass)
207
207
  static VALUE
208
208
  mp_init(struct MPipe *ptr, VALUE self, VALUE rank)
209
209
  {
210
+ int size;
211
+
212
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
210
213
  ptr->rank = NUM2INT(rank);
214
+ if (ptr->rank < 0 || ptr->rank >= size) {
215
+ rb_raise(rb_eArgError,"Invalid rank has value %d but must be nonnegative and less than %d\n",ptr->rank,size);
216
+ }
211
217
  ptr->send_buffer = malloc(mp_buffer_size);
212
218
  ptr->recv_buffer = malloc(mp_buffer_size);
213
219
  return self;
@@ -345,79 +351,104 @@ mp_write(VALUE self, VALUE str)
345
351
  }
346
352
 
347
353
 
348
-
349
- static VALUE
350
- mp_outbuf(char *buf, int len, VALUE outbuf)
354
+ static int
355
+ copy_substr(struct MPipe *ptr, int max_len, VALUE outbuf, int outbuf_pos)
351
356
  {
352
- if (NIL_P(outbuf)) {
353
- return rb_str_new(buf, len);
354
- } else {
355
- rb_str_resize(outbuf, len);
356
- MEMCPY(RSTRING_PTR(outbuf), buf, char, len);
357
- return outbuf;
358
- }
359
- }
360
-
361
- static VALUE
362
- mp_substr(struct MPipe *ptr, VALUE maxlen, VALUE outbuf)
363
- {
364
- int max_len;
365
- int count = ptr->recv_count;
357
+ int len;
366
358
  char *recv_buf = ptr->recv_buffer + ptr->recv_begin;
367
359
 
368
- if (!NIL_P(maxlen)) {
369
- max_len = NUM2INT(maxlen);
370
- if (max_len < 0) {
371
- rb_raise(rb_eArgError, "negative length %d given", max_len);
372
- }
373
- if (max_len < count) {
374
- ptr->recv_begin += max_len;
375
- ptr->recv_count -= max_len;
376
- return mp_outbuf(recv_buf, max_len, outbuf);
377
- }
360
+ len = max_len - outbuf_pos;
361
+ if (len < ptr->recv_count) {
362
+ ptr->recv_begin += len;
363
+ ptr->recv_count -= len;
364
+ } else {
365
+ len = ptr->recv_count;
366
+ ptr->recv_begin = 0;
367
+ ptr->recv_count = 0;
378
368
  }
379
- ptr->recv_begin = 0;
380
- ptr->recv_count = 0;
381
- return mp_outbuf(recv_buf, count, outbuf);
369
+ MEMCPY(RSTRING_PTR(outbuf)+outbuf_pos, recv_buf, char, len);
370
+ return len;
382
371
  }
383
372
 
384
-
373
+ /*
374
+ * call-seq:
375
+ * ios.read(length [, outbuf]) -> string, outbuf, or nil
376
+ *
377
+ * Reads <i>length</i> bytes from the I/O stream.
378
+ *
379
+ * <i>length</i> must be a non-negative integer.
380
+ */
385
381
  static VALUE
386
382
  mp_read(int argc, VALUE *argv, VALUE self)
387
383
  {
388
384
  struct MPipe *ptr = MPipe(self);
389
385
  MPI_Status status;
390
386
  int istat;
391
- int count;
387
+ int outbuf_pos = 0;
388
+ int max_len;
392
389
  VALUE maxlen = Qnil;
393
390
  VALUE outbuf = Qnil;
394
391
 
395
- rb_scan_args(argc, argv, "02", &maxlen, &outbuf);
392
+ rb_scan_args(argc, argv, "11", &maxlen, &outbuf);
393
+
394
+ max_len = NUM2INT(maxlen);
395
+ if (max_len < 0) {
396
+ rb_raise(rb_eArgError, "negative length %d given", max_len);
397
+ }
398
+
399
+ if (NIL_P(outbuf)) {
400
+ outbuf = rb_str_new(0, 0);
401
+ }
402
+ rb_str_resize(outbuf, max_len);
403
+
404
+ if (ptr->recv_count == -1) { // requesting
405
+ istat = MPI_Wait(&ptr->recv_request, &status);
406
+ if (istat != MPI_SUCCESS) {
407
+ rb_raise(rb_eStandardError,"MPI_Wait failed with status=%d",istat);
408
+ }
409
+ MPI_Get_count(&status, MPI_CHAR, &ptr->recv_count);
410
+ }
396
411
 
397
412
  if (ptr->recv_count > 0) {
398
- return mp_substr(ptr, maxlen, outbuf);
413
+ outbuf_pos += copy_substr(ptr, max_len, outbuf, outbuf_pos);
399
414
  }
400
- if (ptr->recv_count == 0) {
415
+
416
+ while (outbuf_pos < max_len) {
401
417
  istat = MPI_Recv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
402
418
  0, MPI_COMM_WORLD, &status);
403
419
  if (istat != MPI_SUCCESS) {
404
420
  rb_raise(rb_eStandardError,"MPI_recv failed with status=%d\n",istat);
405
421
  }
406
- } else { // requesting
407
- istat = MPI_Wait(&ptr->recv_request, &status);
408
- if (istat != MPI_SUCCESS) {
409
- rb_raise(rb_eStandardError,"MPI_Wait failed with status=%d",istat);
410
- }
422
+ MPI_Get_count(&status, MPI_CHAR, &ptr->recv_count);
423
+
424
+ outbuf_pos += copy_substr(ptr, max_len, outbuf, outbuf_pos);
411
425
  }
412
- MPI_Get_count(&status, MPI_CHAR, &count);
413
- ptr->recv_count = count;
414
- return mp_substr(ptr, maxlen, outbuf);
426
+
427
+ return outbuf;
415
428
  }
416
429
 
417
430
 
431
+ static int
432
+ call_test(struct MPipe *ptr)
433
+ {
434
+ MPI_Status status;
435
+ int complete = 0;
436
+ int istat;
437
+
438
+ // if (ptr->recv_count == -1)
439
+ istat = MPI_Test(&ptr->recv_request, &complete, &status);
440
+ if (istat != MPI_SUCCESS) {
441
+ rb_raise(rb_eStandardError,"MPI_Test failed with status=%d",istat);
442
+ }
443
+ if (complete) {
444
+ MPI_Get_count(&status, MPI_CHAR, &ptr->recv_count);
445
+ return ptr->recv_count;
446
+ }
447
+ return 0;
448
+ }
418
449
 
419
450
  static void
420
- request_irecv(struct MPipe *ptr)
451
+ call_irecv(struct MPipe *ptr)
421
452
  {
422
453
  int istat;
423
454
 
@@ -439,7 +470,7 @@ buffered: recv_count=n
439
470
 
440
471
  /*
441
472
  * call-seq:
442
- * mpipe.read_nonblock(integer[, outbuf [, opts]]) -> string
473
+ * mpipe.read_nonblock(maxlen[, outbuf [, opts]]) -> string
443
474
  *
444
475
  * Similar to #read, but raises +EOFError+ at end of string unless the
445
476
  * +exception: false+ option is passed in.
@@ -448,40 +479,60 @@ static VALUE
448
479
  mp_read_nonblock(int argc, VALUE *argv, VALUE self)
449
480
  {
450
481
  struct MPipe *ptr = MPipe(self);
451
- MPI_Status status;
452
- int istat;
453
- int count;
454
- int complete = 0;
482
+ int outbuf_pos = 0;
483
+ int max_len;
455
484
  VALUE maxlen = Qnil;
456
485
  VALUE outbuf = Qnil;
457
486
  VALUE opts = Qnil;
458
- VALUE val;
459
487
 
460
- rb_scan_args(argc, argv, "02:", &maxlen, &outbuf, &opts);
488
+ rb_scan_args(argc, argv, "11:", &maxlen, &outbuf, &opts);
461
489
 
462
- if (ptr->recv_count > 0) {
463
- return mp_substr(ptr, maxlen, outbuf);
490
+ max_len = NUM2INT(maxlen);
491
+ if (max_len < 0) {
492
+ rb_raise(rb_eArgError, "negative length %d given", max_len);
464
493
  }
465
- request_irecv(ptr);
466
- istat = MPI_Test(&ptr->recv_request, &complete, &status);
467
- if (istat != MPI_SUCCESS) {
468
- rb_raise(rb_eStandardError,"MPI_Test failed with status=%d",istat);
494
+
495
+ if (NIL_P(outbuf)) {
496
+ outbuf = rb_str_new(0, 0);
469
497
  }
470
- if (complete) {
471
- MPI_Get_count(&status, MPI_CHAR, &count);
472
- ptr->recv_count = count;
473
- val = mp_substr(ptr, maxlen, outbuf);
474
- } else {
475
- if (!NIL_P(opts) &&
476
- rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse) {
477
- return Qnil;
478
- } else {
479
- rb_raise(eEAGAINWaitReadable,"MPI_Irecv would block");
498
+ rb_str_resize(outbuf, max_len);
499
+
500
+ if (maxlen == 0) {
501
+ return outbuf;
502
+ }
503
+
504
+ if (ptr->recv_count == -1) { // requesting
505
+ if (call_test(ptr) == 0) {
506
+ if (!NIL_P(opts) && rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse) {
507
+ return Qnil;
508
+ } else {
509
+ rb_raise(eEAGAINWaitReadable,"MPI_Irecv would block");
510
+ }
511
+ }
512
+ }
513
+ if (ptr->recv_count > 0) {
514
+ outbuf_pos += copy_substr(ptr, max_len, outbuf, outbuf_pos);
515
+ }
516
+
517
+ while (outbuf_pos < max_len) {
518
+ call_irecv(ptr);
519
+ if (call_test(ptr) == 0) {
520
+ if (outbuf_pos > 0) {
521
+ rb_str_resize(outbuf, outbuf_pos);
522
+ return outbuf;
523
+ } else
524
+ if (!NIL_P(opts) && rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse) {
525
+ return Qnil;
526
+ } else {
527
+ rb_raise(eEAGAINWaitReadable,"MPI_Irecv would block");
528
+ }
480
529
  }
530
+ outbuf_pos += copy_substr(ptr, max_len, outbuf, outbuf_pos);
481
531
  }
482
- return val;
532
+ return outbuf;
483
533
  }
484
534
 
535
+
485
536
  static VALUE
486
537
  mp_s_select(int argc, VALUE *argv, VALUE mod)
487
538
  {
@@ -519,7 +570,7 @@ mp_s_select(int argc, VALUE *argv, VALUE mod)
519
570
  for (i=0; i < incount; i++) {
520
571
  item = RARRAY_AREF(argv[0], i);
521
572
  ptr = MPipe(item);
522
- request_irecv(ptr);
573
+ call_irecv(ptr);
523
574
  ary_of_requests[i] = ptr->recv_request;
524
575
  }
525
576
 
data/samples/t1.rb CHANGED
@@ -1,21 +1,21 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
- puts "buffer_size = %d" % MPipe.buffer_size
4
3
  MPipe.buffer_size = 2**10
5
- puts "buffer_size = %d" % MPipe.buffer_size
6
4
 
7
5
  MPipe.init
8
6
  rank = MPipe::Comm.rank
9
7
  size = MPipe::Comm.size
10
8
  puts "size=%d rank=%d pid=%d" % [size, rank, Process.pid]
11
9
 
12
- # MPipe.buffer_size = 2**13
13
10
  p MPipe.new(0).object_id == MPipe.new(0).object_id
14
11
 
15
12
  if rank == 0
16
13
 
14
+ puts "buffer_size = %d" % MPipe.buffer_size
15
+
16
+ len = "Hello from 0".size
17
17
  (1..size-1).each do |i|
18
- p MPipe.new(i).read
18
+ p MPipe.new(i).read(len)
19
19
  end
20
20
 
21
21
  else
data/samples/t2.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
3
  MPipe.init
4
4
 
@@ -14,7 +14,7 @@ if rank == 0
14
14
  while !pipes.empty?
15
15
  rsel, = MPipe.select(pipes)
16
16
  rsel.each do |r|
17
- p s=r.read_nonblock
17
+ p s=r.read_nonblock(12, exception:false)
18
18
  if /end/ =~ s
19
19
  pipes.delete(r)
20
20
  end
@@ -23,9 +23,11 @@ if rank == 0
23
23
 
24
24
  else
25
25
 
26
+ mp = MPipe.new(0)
26
27
  sleep size-rank
27
- message = "Hello from #{rank}"
28
- MPipe.new(0).write(message)
29
- MPipe.new(0).write("end")
28
+ mp.write("Hello from #{rank}")
29
+ mp.write("end")
30
30
 
31
31
  end
32
+
33
+ MPipe.finalize
data/samples/t3.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
3
  puts "buffer_size = %d" % MPipe.buffer_size
4
4
  MPipe.buffer_size = 2**13
data/samples/t4.rb CHANGED
@@ -1,12 +1,12 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
3
  MPipe.init
4
4
  rank = MPipe::Comm.rank
5
5
  size = MPipe::Comm.size
6
6
  puts "size=%d rank=%d pid=%d" % [size,rank,Process.pid]
7
7
 
8
- def _read(io)
9
- io.read_nonblock
8
+ def _read(io,n)
9
+ io.read_nonblock(n)
10
10
  rescue IO::WaitReadable
11
11
  MPipe.select([io])
12
12
  retry
@@ -17,9 +17,8 @@ if rank == 0
17
17
  pipes = (1..size-1).map{|rank| MPipe.new(rank)}
18
18
 
19
19
  pipes.each do |x|
20
- while !(s = _read(x))
20
+ while !(s = _read(x,12))
21
21
  puts "waiting"
22
- $stdout.flush
23
22
  end
24
23
  p s
25
24
  end
data/samples/t5.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
3
  MPipe.init
4
4
  rank = MPipe::Comm.rank
@@ -14,7 +14,7 @@ if rank == 0
14
14
  rsel, = MPipe.select(pipes)
15
15
  rsel.each do |r|
16
16
  #p r.read_nonblock(6,"")
17
- p s = r.read_nonblock()
17
+ p s = r.read_nonblock(74,exception:false)
18
18
  pipes.delete(r) if /end/ =~ s
19
19
  end
20
20
  end
@@ -22,7 +22,7 @@ if rank == 0
22
22
  else
23
23
 
24
24
  sleep size-rank
25
- message = "Hello from #{rank} - "*500+"end"
26
- MPipe.new(0).write_nonblock(message)
25
+ message = "Hello from #{rank} - "*500+"hello end"
26
+ MPipe.new(0).write(message)
27
27
 
28
28
  end
data/samples/t6.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative "../ext/mpipe"
1
+ require "mpipe"
2
2
 
3
3
  MPipe.init
4
4
  rank = MPipe::Comm.rank
@@ -11,7 +11,7 @@ if rank == 0
11
11
 
12
12
  pipes.each do |r|
13
13
  p r.read(6,"")
14
- p r.read
14
+ p r.read(6)
15
15
  end
16
16
 
17
17
  else
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mpipe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masahiro TANAKA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-03 00:00:00.000000000 Z
11
+ date: 2017-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler