mpipe 0.2.0 → 0.3.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: e4f0bec53a0a6940093b513532384491708117c9
4
- data.tar.gz: 9f15045ca9c5e95c21cb60903d95f3fb16191525
3
+ metadata.gz: b8e5947b77db645ecc5074b784d86c455cd24b4e
4
+ data.tar.gz: aaa1e9b33b288b94339c6859eb1febc1b4123c9a
5
5
  SHA512:
6
- metadata.gz: 50908b6ec00bc10bcef427998eb7f2941bbc1d6d2aadd33cb928e6a1aa37770bdf31663ca027fd8690ba259a4429d6f2336b3fa124e139c123ff4bb4c5ddcdd4
7
- data.tar.gz: 3a06ab215c22444df2914fd583aeebb4aab9138ad68affb090c5949119a41063b006c5d76fdd7b82d5f5704fb7ba31236b0f3264cee41feb67ca66384f5c0e07
6
+ metadata.gz: a94e705f1738c6507f88b2dd5fa0e4a9f8a0e6641e02fdb438e6a269367391392c13f6be5053233f25be0d64868dc95f46e763edb106abe818938e2269265144
7
+ data.tar.gz: d2a00d00b9f2f77a871a90aa5875d9edd03ddd352c56f5113603523faeda1830b1eaf3dd16ae2515215dd5db5869dbd9e2a21371dbbd41ed43af8fda4fbc94d1
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # MPipe
2
2
 
3
- Ruby's IO.pipe emulation over MPI
3
+ Ruby's IO.pipe emulation using MPI
4
4
 
5
5
  [GitHub](https://github.com/masa16/mpipe) | [RubyGems](https://rubygems.org/gems/mpipe)
6
6
 
7
7
  ## Requirement
8
8
 
9
- Message Passing Interface (MPI) framework such as
9
+ Message Passing Interface (MPI) framework such as
10
10
  [OpenMPI](https://www.open-mpi.org/), [MPICH](https://www.mpich.org/), etc.
11
11
 
12
- Commands:
12
+ Required commands:
13
13
  * mpicc - Compiler for MPI programs.
14
14
  * mpirun - Command to run MPI program.
15
15
 
@@ -43,7 +43,7 @@ puts "size=%d rank=%d pid=%d" % [size,rank,Process.pid]
43
43
  if rank == 0
44
44
 
45
45
  (1..size-1).each do |r|
46
- p MPipe.new(r).read
46
+ p MPipe.new(r).read(12)
47
47
  end
48
48
 
49
49
  else
@@ -79,7 +79,11 @@ mp = MPipe.new(rank) -- returns pipe to MPI process with rank.
79
79
  mp.write(str) -- emulate IO#write.
80
80
  mp.read(length,outbuf=nil) -- emulate IO#read.
81
81
  mp.read_nonblock(maxlen,outbuf=nil,excepton:true) -- emulate IO#read_nonblock.
82
- MPipe.select(array_of_mpipe) -- emulate IO.select
82
+
83
+ MPipe.select(rd_ary, [wt_ary, er_ary, timeout]) -- emulate IO.select
84
+ MPipe.min_polling_intercal=(sec) -- initial polling interval in MPipe.select.
85
+ MPipe.max_polling_intercal=(sec) -- final polling interval in MPipe.select.
86
+ (polling intervals = min, min*2, min*4, min*8, ..., max, max, ...)
83
87
  ```
84
88
 
85
89
  ## Contributing
@@ -1,10 +1,9 @@
1
+ //#include <sys/time.h>
1
2
  #include "ruby.h"
2
3
  #include "ruby/io.h"
3
4
  //#include "ruby/encoding.h"
4
5
  #include "mpi.h"
5
6
 
6
- #define MPIPE_VERSION "0.2.0"
7
-
8
7
  static int mp_buffer_size = 4098;
9
8
  static int mp_initialized = 0;
10
9
  static int mp_finalized = 0;
@@ -254,7 +253,16 @@ mp_s_new(VALUE klass, VALUE vrank)
254
253
  }
255
254
 
256
255
 
257
- #if 0
256
+ /*
257
+ * Returns +rank+.
258
+ */
259
+ static VALUE
260
+ mp_rank(VALUE self)
261
+ {
262
+ struct MPipe *ptr = MPipe(self);
263
+ return INT2NUM(ptr->rank);
264
+ }
265
+
258
266
  /*
259
267
  * Returns +false+. Just for compatibility to IO.
260
268
  */
@@ -264,7 +272,6 @@ mp_false(VALUE self)
264
272
  MPipe(self);
265
273
  return Qfalse;
266
274
  }
267
- #endif
268
275
 
269
276
  /*
270
277
  * Returns +nil+. Just for compatibility to IO.
@@ -321,6 +328,8 @@ mp_unimpl(int argc, VALUE *argv, VALUE self)
321
328
  #endif
322
329
 
323
330
  #define mp_close mp_nil
331
+ #define mp_flush mp_nil
332
+ #define mp_closed_p mp_false
324
333
 
325
334
  static VALUE
326
335
  mp_write(VALUE self, VALUE str)
@@ -342,12 +351,12 @@ mp_write(VALUE self, VALUE str)
342
351
  istat = MPI_Send(ptr->send_buffer, count, MPI_CHAR, ptr->rank,
343
352
  0, MPI_COMM_WORLD);
344
353
  if (istat != MPI_SUCCESS) {
345
- rb_raise(rb_eStandardError,"MPI_send failed with status=%d\n",istat);
354
+ rb_raise(rb_eStandardError,"MPI_Send failed with status=%d\n",istat);
346
355
  }
347
356
 
348
357
  pos += count;
349
358
  }
350
- return self;
359
+ return INT2NUM(pos);
351
360
  }
352
361
 
353
362
 
@@ -417,7 +426,7 @@ mp_read(int argc, VALUE *argv, VALUE self)
417
426
  istat = MPI_Recv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
418
427
  0, MPI_COMM_WORLD, &status);
419
428
  if (istat != MPI_SUCCESS) {
420
- rb_raise(rb_eStandardError,"MPI_recv failed with status=%d\n",istat);
429
+ rb_raise(rb_eStandardError,"MPI_Recv failed with status=%d\n",istat);
421
430
  }
422
431
  MPI_Get_count(&status, MPI_CHAR, &ptr->recv_count);
423
432
 
@@ -533,61 +542,26 @@ mp_read_nonblock(int argc, VALUE *argv, VALUE self)
533
542
  }
534
543
 
535
544
 
545
+ /*
546
+ * call-seq:
547
+ * mpipe.test_recv -> true or false
548
+ *
549
+ * calls MPI_Test
550
+ */
536
551
  static VALUE
537
- mp_s_select(int argc, VALUE *argv, VALUE mod)
552
+ mp_test_recv(VALUE self)
538
553
  {
539
- struct MPipe *ptr;
540
- MPI_Request *ary_of_requests;
541
- int *ary_of_indices;
542
- MPI_Status *ary_of_statuses;
543
- int incount, outcount;
544
- int i, count, istat;
545
- VALUE rd_ary, result_ary, item;
546
-
547
- if (argc==0) {
548
- rb_raise(rb_eArgError, "no argument");
549
- }
550
- incount = RARRAY_LEN(argv[0]);
551
-
552
- result_ary = rb_ary_new();
553
- rd_ary = rb_ary_new();
554
- rb_ary_push(result_ary, rd_ary);
555
- for (i=0; i < incount; i++) {
556
- item = RARRAY_AREF(argv[0], i);
557
- ptr = MPipe(item);
558
- if (ptr->recv_count > 0) {
559
- rb_ary_push(rd_ary, item);
560
- }
561
- }
562
- if (RARRAY_LEN(rd_ary) > 0) {
563
- return result_ary;
564
- }
565
-
566
- ary_of_requests = ALLOCA_N(MPI_Request, incount);
567
- ary_of_statuses = ALLOCA_N(MPI_Status, incount);
568
- ary_of_indices = ALLOCA_N(int, incount);
569
-
570
- for (i=0; i < incount; i++) {
571
- item = RARRAY_AREF(argv[0], i);
572
- ptr = MPipe(item);
573
- call_irecv(ptr);
574
- ary_of_requests[i] = ptr->recv_request;
575
- }
554
+ struct MPipe *ptr = MPipe(self);
576
555
 
577
- istat = MPI_Waitsome(incount, ary_of_requests,
578
- &outcount, ary_of_indices, ary_of_statuses);
579
- if (istat != MPI_SUCCESS) {
580
- rb_raise(rb_eStandardError,"MPI_Waitany failed with status=%d",istat);
556
+ call_irecv(ptr);
557
+ if (ptr->recv_count == -1) { // requesting
558
+ call_test(ptr);
581
559
  }
582
-
583
- for (i=0; i < outcount; i++) {
584
- item = RARRAY_AREF(argv[0], ary_of_indices[i]);
585
- MPI_Get_count(&ary_of_statuses[i], MPI_BYTE, &count);
586
- ptr = MPipe(item);
587
- ptr->recv_count = count;
588
- rb_ary_push(rd_ary, item);
560
+ if (ptr->recv_count > 0) {
561
+ return Qtrue;
562
+ } else {
563
+ return Qfalse;
589
564
  }
590
- return result_ary;
591
565
  }
592
566
 
593
567
 
@@ -604,7 +578,6 @@ void Init_mpipe()
604
578
  rb_define_module_function(cMPipe, "buffer_size", mp_mpi_buffer_size, 0);
605
579
  rb_define_module_function(cMPipe, "buffer_size=", mp_mpi_set_buffer_size, 1);
606
580
 
607
- rb_define_const(cMPipe, "VERSION", rb_str_new2(MPIPE_VERSION));
608
581
  rb_define_const(cMPipe, "MPI_VERSION", INT2NUM(MPI_VERSION));
609
582
  rb_define_const(cMPipe, "MPI_SUBVERSION", INT2NUM(MPI_SUBVERSION));
610
583
  rb_define_const(cMPipe, "SUCCESS", INT2NUM(MPI_SUCCESS));
@@ -625,9 +598,11 @@ void Init_mpipe()
625
598
  rb_define_method(cMPipe, "print", mp_write, 1);
626
599
  rb_define_method(cMPipe, "read", mp_read, -1);
627
600
  rb_define_method(cMPipe, "read_nonblock", mp_read_nonblock, -1);
628
- rb_define_method(cMPipe, "close", mp_close, 1);
629
-
630
- rb_define_singleton_method(cMPipe, "select", mp_s_select, -1);
601
+ rb_define_method(cMPipe, "flush", mp_flush, 0);
602
+ rb_define_method(cMPipe, "close", mp_close, 0);
603
+ rb_define_method(cMPipe, "closed?", mp_closed_p, 0);
604
+ rb_define_method(cMPipe, "test_recv", mp_test_recv, 0);
605
+ rb_define_method(cMPipe, "rank", mp_rank, 0);
631
606
 
632
607
  sym_exception = ID2SYM(rb_intern("exception"));
633
608
  id_allocated_mpipe = rb_intern("allocated_mpipe");
@@ -0,0 +1,129 @@
1
+ require "mpipe.so"
2
+ require "mpipe/version"
3
+
4
+ class MPipe
5
+
6
+ @@min_poll = 0.01
7
+ @@max_poll = 0.32
8
+
9
+ def self.min_polling_interval=(time)
10
+ @@min_poll = time
11
+ end
12
+
13
+ def self.max_polling_interval=(time)
14
+ @@max_poll = time
15
+ end
16
+
17
+ # emulate IO.select
18
+ def self.select(rd_ary, wt_ary=nil, er_ary=nil, timeout=nil)
19
+ rd_ary = [] if rd_ary.nil?
20
+ wt_ary = [] if wt_ary.nil?
21
+ rd_mpi = []
22
+ rd_io = []
23
+ wt_io = []
24
+ rd_ret = Array.new(rd_ary.size)
25
+ wt_ret = Array.new(wt_ary.size)
26
+ rd_idx = {}
27
+ wt_idx = {}
28
+ found = false
29
+
30
+ rd_ary.each_with_index do |rd,i|
31
+ rd_idx[rd] = i
32
+ case rd
33
+ when MPipe
34
+ rd_mpi << rd
35
+ if rd.test_recv
36
+ rd_ret[i] = rd
37
+ found = true
38
+ end
39
+ when IO
40
+ rd_io << rd
41
+ else
42
+ raise ArgumentError, "elements should be IO or MPipe"
43
+ end
44
+ end
45
+
46
+ wt_ary.each_with_index do |wt,i|
47
+ wt_idx[wt] = i
48
+ case wt
49
+ when MPipe
50
+ wt_ret[i] = wt
51
+ found = true
52
+ when IO
53
+ wt_io << wt
54
+ else
55
+ raise ArgumentError, "elements should be IO or MPipe"
56
+ end
57
+ end
58
+
59
+ if er_ary
60
+ er_ary.each do |er|
61
+ if !er.kind_of?(IO)
62
+ raise ArgumentError, "er_ary contains non-IO object"
63
+ end
64
+ end
65
+ end
66
+
67
+ time_start = Time.now
68
+
69
+ # first check
70
+ rd_res,wt_res,er_res = IO.select(rd_io, wt_io, er_ary, 0)
71
+ if rd_res
72
+ rd_res.each{|io| rd_ret[rd_idx[io]] = io}
73
+ found = true
74
+ end
75
+ if wt_res
76
+ wt_res.each{|io| wt_ret[wt_idx[io]] = io}
77
+ found = true
78
+ end
79
+ if er_res
80
+ found = true
81
+ end
82
+ if found
83
+ return [rd_ret.compact, wt_ret.compact, er_res]
84
+ end
85
+
86
+ dt = @@min_poll
87
+ max_dt = @@max_poll
88
+ loop do
89
+ if timeout
90
+ elap = Time.now - time_start
91
+ if timeout <= elap
92
+ return nil
93
+ else
94
+ dto = timeout - elap
95
+ dt = (dto < dt) ? dto : dt
96
+ end
97
+ end
98
+
99
+ # check with timeout
100
+ rd_res,wt_res,er_res = IO.select(rd_io, wt_io, er_ary, dt)
101
+
102
+ if rd_res
103
+ rd_res.each{|io| rd_ret[rd_idx[io]] = io}
104
+ found = true
105
+ end
106
+ if wt_res
107
+ wt_res.each{|io| wt_ret[wt_idx[io]] = io}
108
+ found = true
109
+ end
110
+ if er_res
111
+ found = true
112
+ end
113
+ rd_mpi.each do |mp|
114
+ if mp.test_recv
115
+ rd_ret[rd_idx[mp]] = mp
116
+ found = true
117
+ end
118
+ end
119
+ if found
120
+ return [rd_ret.compact,wt_ret.compact,er_res]
121
+ end
122
+ if dt != max_dt
123
+ dt *= 2 if dt < max_dt
124
+ dt = max_dt if dt > max_dt
125
+ end
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,3 @@
1
+ class MPipe
2
+ VERSION = "0.3.0"
3
+ end
@@ -1,24 +1,13 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
-
5
1
  # get version
6
- open("ext/mpipe/mpipe.c") do |f|
7
- f.each_line do |l|
8
- if /MPIPE_VERSION "([\d.]+)"/ =~ l
9
- VERSION = $1
10
- break
11
- end
12
- end
13
- end
2
+ require_relative "lib/mpipe/version"
14
3
 
15
4
  Gem::Specification.new do |spec|
16
5
  spec.name = "mpipe"
17
- spec.version = VERSION
6
+ spec.version = MPipe::VERSION
18
7
  spec.authors = ["Masahiro TANAKA"]
19
8
  spec.email = ["masa16.tanaka@gmail.com"]
20
- spec.description = %q{MPipe - IO.pipe emulation over MPI.}
21
- spec.summary = %q{MPipe - IO.pipe emulation over MPI}
9
+ spec.description = %q{MPipe - IO.pipe emulation using MPI.}
10
+ spec.summary = %q{MPipe - IO.pipe emulation using MPI}
22
11
  spec.homepage = "https://github.com/masa16/mpipe"
23
12
  spec.license = "MIT"
24
13
 
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.2.0
4
+ version: 0.3.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-06 00:00:00.000000000 Z
11
+ date: 2017-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: MPipe - IO.pipe emulation over MPI.
41
+ description: MPipe - IO.pipe emulation using MPI.
42
42
  email:
43
43
  - masa16.tanaka@gmail.com
44
44
  executables: []
@@ -52,6 +52,8 @@ files:
52
52
  - Rakefile
53
53
  - ext/mpipe/extconf.rb
54
54
  - ext/mpipe/mpipe.c
55
+ - lib/mpipe.rb
56
+ - lib/mpipe/version.rb
55
57
  - mpipe.gemspec
56
58
  - samples/t1.rb
57
59
  - samples/t2.rb
@@ -83,5 +85,5 @@ rubyforge_project:
83
85
  rubygems_version: 2.6.8
84
86
  signing_key:
85
87
  specification_version: 4
86
- summary: MPipe - IO.pipe emulation over MPI
88
+ summary: MPipe - IO.pipe emulation using MPI
87
89
  test_files: []