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 +4 -4
- data/README.md +9 -5
- data/ext/mpipe/mpipe.c +36 -61
- data/lib/mpipe.rb +129 -0
- data/lib/mpipe/version.rb +3 -0
- data/mpipe.gemspec +4 -15
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8e5947b77db645ecc5074b784d86c455cd24b4e
|
4
|
+
data.tar.gz: aaa1e9b33b288b94339c6859eb1febc1b4123c9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
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
|
-
|
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
|
data/ext/mpipe/mpipe.c
CHANGED
@@ -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
|
-
|
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,"
|
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
|
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,"
|
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
|
-
|
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
|
-
|
578
|
-
|
579
|
-
|
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
|
-
|
584
|
-
|
585
|
-
|
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, "
|
629
|
-
|
630
|
-
|
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");
|
data/lib/mpipe.rb
ADDED
@@ -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
|
data/mpipe.gemspec
CHANGED
@@ -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
|
-
|
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
|
21
|
-
spec.summary = %q{MPipe - IO.pipe emulation
|
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.
|
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-
|
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
|
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
|
88
|
+
summary: MPipe - IO.pipe emulation using MPI
|
87
89
|
test_files: []
|