mpipe 0.2.0 → 0.3.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: 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: []