mpipe 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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