mpipe 0.1.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 +7 -0
- data/.gitignore +49 -0
- data/Gemfile +4 -0
- data/README.md +76 -0
- data/Rakefile +2 -0
- data/ext/mpipe/extconf.rb +9 -0
- data/ext/mpipe/mpipe.c +584 -0
- data/mpipe.gemspec +36 -0
- data/samples/t1.rb +28 -0
- data/samples/t2.rb +31 -0
- data/samples/t3.rb +28 -0
- data/samples/t4.rb +33 -0
- data/samples/t5.rb +28 -0
- data/samples/t6.rb +23 -0
- data/setup.rb +1295 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 638f1385e64bf50aedff83fbdec7cf8de6f2e63b
|
4
|
+
data.tar.gz: e16b54cc652d0f6503cd4776bf716903fcaf2703
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: df234ecdd079cb9b24f7afb9c8c1f8ce585cd247f6286a4c49e8484b5b7296ec2445ffb3cf603d5a2ef69be8dd567b6c8a03905f6c0d3a96b793869c76e2839f
|
7
|
+
data.tar.gz: 5872d1e9ab4b7536d50d55a9cb778a9d43cc140b81e6bdaed70388b19af051956039e03554338ee11399a8f56af39c40c10a9130f0e2bdca67deb0acc9172d7a
|
data/.gitignore
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
tmp/
|
12
|
+
|
13
|
+
## Specific to RubyMotion:
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
.yardoc/
|
20
|
+
_yardoc/
|
21
|
+
doc/
|
22
|
+
rdoc/
|
23
|
+
|
24
|
+
## Environment normalization:
|
25
|
+
/.bundle/
|
26
|
+
/vendor/bundle
|
27
|
+
/lib/bundler/man/
|
28
|
+
|
29
|
+
# for a library or gem, you might want to ignore these files since the code is
|
30
|
+
# intended to run in multiple environments; otherwise, check them in:
|
31
|
+
Gemfile.lock
|
32
|
+
.ruby-version
|
33
|
+
.ruby-gemset
|
34
|
+
|
35
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
36
|
+
.rvmrc
|
37
|
+
|
38
|
+
# setup.rb
|
39
|
+
/SetupConfig
|
40
|
+
/SetupReceipt
|
41
|
+
|
42
|
+
# Build files for extension
|
43
|
+
*~
|
44
|
+
*.o
|
45
|
+
*.so
|
46
|
+
TAGS
|
47
|
+
t.rb
|
48
|
+
*.bak[0-9]
|
49
|
+
bak
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# MPipe
|
2
|
+
|
3
|
+
Ruby's IO.pipe emulation over MPI
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'mpipe'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install mpipe
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
test code: t.rb
|
24
|
+
```ruby
|
25
|
+
require "mpipe"
|
26
|
+
|
27
|
+
MPipe.init
|
28
|
+
rank = MPipe::Comm.rank
|
29
|
+
size = MPipe::Comm.size
|
30
|
+
puts "size=%d rank=%d pid=%d" % [size,rank,Process.pid]
|
31
|
+
|
32
|
+
if rank == 0
|
33
|
+
|
34
|
+
(1..size-1).each do |r|
|
35
|
+
p MPipe.new(r).read
|
36
|
+
end
|
37
|
+
|
38
|
+
else
|
39
|
+
|
40
|
+
sleep rank
|
41
|
+
MPipe.new(0).write("Hello from #{rank}")
|
42
|
+
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
execute:
|
47
|
+
```
|
48
|
+
$ mpirun -np 4 ruby t.rb
|
49
|
+
size=4 rank=0 pid=10353
|
50
|
+
"Hello from 1"
|
51
|
+
size=4 rank=1 pid=10354
|
52
|
+
"Hello from 2"
|
53
|
+
size=4 rank=2 pid=10355
|
54
|
+
"Hello from 3"
|
55
|
+
size=4 rank=3 pid=10356
|
56
|
+
```
|
57
|
+
|
58
|
+
## API
|
59
|
+
|
60
|
+
```
|
61
|
+
MPipe.init(*args) -- calls MPI_Init()
|
62
|
+
MPipe.finalize -- calls MPI_Finalize()
|
63
|
+
MPipe.abort(errorcode) -- calls MPI_Abort(MPI_COMM_WORLD, errorcode)
|
64
|
+
MPipe::Comm.rank -- calls MPI_Comm_rank(), return the rank of this process.
|
65
|
+
MPipe::Comm.size -- calls MPI_Comm_size(), return the size of this environment.
|
66
|
+
|
67
|
+
mp = MPipe.new(rank) -- returns pipe to MPI process with rank.
|
68
|
+
mp.write(str) -- emulate IO#write.
|
69
|
+
mp.read(maxlen,outbuf) -- emulate IO#read.
|
70
|
+
mp.read_nonblock(maxlen,outbuf) -- emulate IO#read_nonblock.
|
71
|
+
MPipe.select(array_of_mpipe) -- emulate IO.select
|
72
|
+
```
|
73
|
+
|
74
|
+
## Contributing
|
75
|
+
|
76
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/Masahiro TANAKA/mpipe.
|
data/Rakefile
ADDED
data/ext/mpipe/mpipe.c
ADDED
@@ -0,0 +1,584 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "ruby/io.h"
|
3
|
+
//#include "ruby/encoding.h"
|
4
|
+
#include "mpi.h"
|
5
|
+
|
6
|
+
#define MPIPE_VERSION "0.1.0"
|
7
|
+
|
8
|
+
static int mp_buffer_size = 4098;
|
9
|
+
static int mp_initialized = 0;
|
10
|
+
static int mp_finalized = 0;
|
11
|
+
static VALUE sym_exception;
|
12
|
+
static VALUE eEAGAINWaitReadable;
|
13
|
+
static ID id_allocated_mpipe;
|
14
|
+
|
15
|
+
struct MPipe {
|
16
|
+
int rank;
|
17
|
+
char *send_buffer;
|
18
|
+
char *recv_buffer;
|
19
|
+
MPI_Request send_request;
|
20
|
+
MPI_Request recv_request;
|
21
|
+
int send_count;
|
22
|
+
int recv_count;
|
23
|
+
int recv_begin;
|
24
|
+
};
|
25
|
+
|
26
|
+
#define IS_MPIPE(obj) (rb_typeddata_is_kind_of((obj), &mp_data_type))
|
27
|
+
#define error_inval(msg) (rb_syserr_fail(EINVAL, msg))
|
28
|
+
//#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string))
|
29
|
+
#define get_enc(ptr) ((ptr)->enc)
|
30
|
+
|
31
|
+
static void
|
32
|
+
mp_finalize()
|
33
|
+
{
|
34
|
+
if (mp_initialized && !mp_finalized) {
|
35
|
+
mp_finalized = 1;
|
36
|
+
MPI_Finalize();
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE
|
41
|
+
mp_mpi_init(int argc, VALUE *argv, VALUE klass)
|
42
|
+
{
|
43
|
+
char **cargv;
|
44
|
+
VALUE progname, mpipe_ary;
|
45
|
+
int i, size;
|
46
|
+
|
47
|
+
cargv = ALLOCA_N(char *, argc+1);
|
48
|
+
progname = rb_gv_get("$0");
|
49
|
+
cargv[0] = StringValueCStr(progname);
|
50
|
+
|
51
|
+
for(i=0; i<argc; i++) {
|
52
|
+
if (TYPE(argv[i]) == T_STRING) {
|
53
|
+
cargv[i+1] = StringValueCStr(argv[i]);
|
54
|
+
} else {
|
55
|
+
rb_raise(rb_eArgError, "argument must be string");
|
56
|
+
}
|
57
|
+
}
|
58
|
+
argc++;
|
59
|
+
|
60
|
+
MPI_Init(&argc, &cargv);
|
61
|
+
|
62
|
+
if (mp_initialized) {
|
63
|
+
return Qnil;
|
64
|
+
} else {
|
65
|
+
mp_initialized = 1;
|
66
|
+
}
|
67
|
+
atexit(mp_finalize);
|
68
|
+
|
69
|
+
MPI_Comm_size(MPI_COMM_WORLD, &size);
|
70
|
+
mpipe_ary = rb_ary_new2(size);
|
71
|
+
rb_ivar_set(klass, id_allocated_mpipe, mpipe_ary);
|
72
|
+
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
static VALUE
|
77
|
+
mp_mpi_finalize(VALUE klass)
|
78
|
+
{
|
79
|
+
mp_finalize();
|
80
|
+
return Qnil;
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE
|
84
|
+
mp_mpi_abort(VALUE klass, VALUE rerror)
|
85
|
+
{
|
86
|
+
int ierror;
|
87
|
+
|
88
|
+
ierror = MPI_Abort(MPI_COMM_WORLD, NUM2INT(rerror));
|
89
|
+
return INT2NUM(ierror);
|
90
|
+
}
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
mp_mpi_buffer_size(VALUE mod)
|
94
|
+
{
|
95
|
+
return INT2NUM(mp_buffer_size);
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE
|
99
|
+
mp_mpi_set_buffer_size(VALUE mod, VALUE size)
|
100
|
+
{
|
101
|
+
if (mp_initialized) {
|
102
|
+
rb_raise(rb_eStandardError,"buffer_size must be set before MPipe.init");
|
103
|
+
}
|
104
|
+
mp_buffer_size = NUM2INT(size);
|
105
|
+
return size;
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE
|
109
|
+
mp_comm_size(VALUE self)
|
110
|
+
{
|
111
|
+
int size;
|
112
|
+
|
113
|
+
MPI_Comm_size(MPI_COMM_WORLD, &size);
|
114
|
+
return INT2NUM(size);
|
115
|
+
}
|
116
|
+
|
117
|
+
static VALUE
|
118
|
+
mp_comm_rank(VALUE self)
|
119
|
+
{
|
120
|
+
int rank;
|
121
|
+
|
122
|
+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
|
123
|
+
return INT2NUM(rank);
|
124
|
+
}
|
125
|
+
|
126
|
+
// ---------------------------------------------------------
|
127
|
+
|
128
|
+
static struct MPipe *
|
129
|
+
mp_alloc(void)
|
130
|
+
{
|
131
|
+
struct MPipe *ptr = ALLOC(struct MPipe);
|
132
|
+
ptr->rank = -1;
|
133
|
+
ptr->send_buffer = 0;
|
134
|
+
ptr->recv_buffer = 0;
|
135
|
+
ptr->send_count = 0;
|
136
|
+
ptr->recv_count = 0;
|
137
|
+
ptr->recv_begin = 0;
|
138
|
+
return ptr;
|
139
|
+
}
|
140
|
+
|
141
|
+
static void
|
142
|
+
mp_free(void *p)
|
143
|
+
{
|
144
|
+
struct MPipe *ptr = p;
|
145
|
+
|
146
|
+
//if (--ptr->count <= 0) {
|
147
|
+
if (ptr) {
|
148
|
+
|
149
|
+
if (ptr->send_count == -1) {
|
150
|
+
MPI_Request_free(&ptr->send_request);
|
151
|
+
ptr->send_count = 0;
|
152
|
+
}
|
153
|
+
if (ptr->recv_count == -1) {
|
154
|
+
MPI_Request_free(&ptr->recv_request);
|
155
|
+
ptr->recv_count = 0;
|
156
|
+
}
|
157
|
+
if (ptr->send_buffer) {
|
158
|
+
xfree(ptr->send_buffer);
|
159
|
+
ptr->send_buffer = 0;
|
160
|
+
}
|
161
|
+
if (ptr->recv_buffer) {
|
162
|
+
xfree(ptr->recv_buffer);
|
163
|
+
ptr->recv_buffer = 0;
|
164
|
+
}
|
165
|
+
|
166
|
+
xfree(ptr);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
static size_t
|
171
|
+
mp_memsize(const void *p)
|
172
|
+
{
|
173
|
+
return sizeof(struct MPipe) + mp_buffer_size*2;
|
174
|
+
}
|
175
|
+
|
176
|
+
static const rb_data_type_t mp_data_type = {
|
177
|
+
"mpipe",
|
178
|
+
{
|
179
|
+
0,
|
180
|
+
mp_free,
|
181
|
+
mp_memsize,
|
182
|
+
},
|
183
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
184
|
+
};
|
185
|
+
|
186
|
+
#define check_mpipe(self) ((struct MPipe*)rb_check_typeddata((self), &mp_data_type))
|
187
|
+
|
188
|
+
static struct MPipe*
|
189
|
+
get_mpipe(VALUE self)
|
190
|
+
{
|
191
|
+
struct MPipe *ptr = check_mpipe(rb_io_taint_check(self));
|
192
|
+
|
193
|
+
if (!ptr) {
|
194
|
+
rb_raise(rb_eIOError, "uninitialized stream");
|
195
|
+
}
|
196
|
+
return ptr;
|
197
|
+
}
|
198
|
+
|
199
|
+
#define MPipe(obj) get_mpipe(obj)
|
200
|
+
|
201
|
+
static VALUE
|
202
|
+
mp_s_allocate(VALUE klass)
|
203
|
+
{
|
204
|
+
return TypedData_Wrap_Struct(klass, &mp_data_type, 0);
|
205
|
+
}
|
206
|
+
|
207
|
+
static VALUE
|
208
|
+
mp_init(struct MPipe *ptr, VALUE self, VALUE rank)
|
209
|
+
{
|
210
|
+
ptr->rank = NUM2INT(rank);
|
211
|
+
ptr->send_buffer = malloc(mp_buffer_size);
|
212
|
+
ptr->recv_buffer = malloc(mp_buffer_size);
|
213
|
+
return self;
|
214
|
+
}
|
215
|
+
|
216
|
+
/*
|
217
|
+
* call-seq: MPipe.new(string=""[, mode])
|
218
|
+
*
|
219
|
+
* Creates new MPipe instance from with _string_ and _mode_.
|
220
|
+
*/
|
221
|
+
static VALUE
|
222
|
+
mp_initialize(VALUE self, VALUE rank)
|
223
|
+
{
|
224
|
+
struct MPipe *ptr = check_mpipe(self);
|
225
|
+
|
226
|
+
if (!ptr) {
|
227
|
+
DATA_PTR(self) = ptr = mp_alloc();
|
228
|
+
}
|
229
|
+
rb_call_super(0, 0);
|
230
|
+
return mp_init(ptr, self, rank);
|
231
|
+
}
|
232
|
+
|
233
|
+
/* :nodoc: */
|
234
|
+
static VALUE
|
235
|
+
mp_s_new(VALUE klass, VALUE vrank)
|
236
|
+
{
|
237
|
+
VALUE mpipe, mpipe_ary;
|
238
|
+
int rank;
|
239
|
+
|
240
|
+
rank = NUM2INT(vrank);
|
241
|
+
mpipe_ary = rb_ivar_get(klass, id_allocated_mpipe);
|
242
|
+
mpipe = rb_ary_entry(mpipe_ary, rank);
|
243
|
+
if (NIL_P(mpipe)) {
|
244
|
+
mpipe = rb_class_new_instance(1, &vrank, klass);
|
245
|
+
rb_ary_store(mpipe_ary, rank, mpipe);
|
246
|
+
}
|
247
|
+
return mpipe;
|
248
|
+
}
|
249
|
+
|
250
|
+
|
251
|
+
#if 0
|
252
|
+
/*
|
253
|
+
* Returns +false+. Just for compatibility to IO.
|
254
|
+
*/
|
255
|
+
static VALUE
|
256
|
+
mp_false(VALUE self)
|
257
|
+
{
|
258
|
+
MPipe(self);
|
259
|
+
return Qfalse;
|
260
|
+
}
|
261
|
+
#endif
|
262
|
+
|
263
|
+
/*
|
264
|
+
* Returns +nil+. Just for compatibility to IO.
|
265
|
+
*/
|
266
|
+
static VALUE
|
267
|
+
mp_nil(VALUE self)
|
268
|
+
{
|
269
|
+
MPipe(self);
|
270
|
+
return Qnil;
|
271
|
+
}
|
272
|
+
|
273
|
+
#if 0
|
274
|
+
/*
|
275
|
+
* Returns *pipempi* itself. Just for compatibility to IO.
|
276
|
+
*/
|
277
|
+
static VALUE
|
278
|
+
mp_self(VALUE self)
|
279
|
+
{
|
280
|
+
MPipe(self);
|
281
|
+
return self;
|
282
|
+
}
|
283
|
+
|
284
|
+
/*
|
285
|
+
* Returns 0. Just for compatibility to IO.
|
286
|
+
*/
|
287
|
+
static VALUE
|
288
|
+
mp_0(VALUE self)
|
289
|
+
{
|
290
|
+
MPipe(self);
|
291
|
+
return INT2FIX(0);
|
292
|
+
}
|
293
|
+
|
294
|
+
/*
|
295
|
+
* Returns the argument unchanged. Just for compatibility to IO.
|
296
|
+
*/
|
297
|
+
static VALUE
|
298
|
+
mp_first(VALUE self, VALUE arg)
|
299
|
+
{
|
300
|
+
MPipe(self);
|
301
|
+
return arg;
|
302
|
+
}
|
303
|
+
|
304
|
+
/*
|
305
|
+
* Raises NotImplementedError.
|
306
|
+
*/
|
307
|
+
static VALUE
|
308
|
+
mp_unimpl(int argc, VALUE *argv, VALUE self)
|
309
|
+
{
|
310
|
+
MPipe(self);
|
311
|
+
rb_notimplement();
|
312
|
+
|
313
|
+
UNREACHABLE;
|
314
|
+
}
|
315
|
+
#endif
|
316
|
+
|
317
|
+
#define mp_close mp_nil
|
318
|
+
|
319
|
+
static VALUE
|
320
|
+
mp_write(VALUE self, VALUE str)
|
321
|
+
{
|
322
|
+
struct MPipe *ptr = MPipe(self);
|
323
|
+
int istat;
|
324
|
+
int pos, count;
|
325
|
+
|
326
|
+
str = StringValue(str);
|
327
|
+
pos = 0;
|
328
|
+
|
329
|
+
while (pos < RSTRING_LEN(str)) {
|
330
|
+
count = RSTRING_LEN(str) - pos;
|
331
|
+
if (count > mp_buffer_size) {
|
332
|
+
count = mp_buffer_size;
|
333
|
+
}
|
334
|
+
memcpy(ptr->send_buffer, RSTRING_PTR(str)+pos, count);
|
335
|
+
|
336
|
+
istat = MPI_Send(ptr->send_buffer, count, MPI_CHAR, ptr->rank,
|
337
|
+
0, MPI_COMM_WORLD);
|
338
|
+
if (istat != MPI_SUCCESS) {
|
339
|
+
rb_raise(rb_eStandardError,"MPI_send failed with status=%d\n",istat);
|
340
|
+
}
|
341
|
+
|
342
|
+
pos += count;
|
343
|
+
}
|
344
|
+
return self;
|
345
|
+
}
|
346
|
+
|
347
|
+
|
348
|
+
|
349
|
+
static VALUE
|
350
|
+
mp_outbuf(char *buf, int len, VALUE outbuf)
|
351
|
+
{
|
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;
|
366
|
+
char *recv_buf = ptr->recv_buffer + ptr->recv_begin;
|
367
|
+
|
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
|
+
}
|
378
|
+
}
|
379
|
+
ptr->recv_begin = 0;
|
380
|
+
ptr->recv_count = 0;
|
381
|
+
return mp_outbuf(recv_buf, count, outbuf);
|
382
|
+
}
|
383
|
+
|
384
|
+
|
385
|
+
static VALUE
|
386
|
+
mp_read(int argc, VALUE *argv, VALUE self)
|
387
|
+
{
|
388
|
+
struct MPipe *ptr = MPipe(self);
|
389
|
+
MPI_Status status;
|
390
|
+
int istat;
|
391
|
+
int count;
|
392
|
+
VALUE maxlen = Qnil;
|
393
|
+
VALUE outbuf = Qnil;
|
394
|
+
|
395
|
+
rb_scan_args(argc, argv, "02", &maxlen, &outbuf);
|
396
|
+
|
397
|
+
if (ptr->recv_count > 0) {
|
398
|
+
return mp_substr(ptr, maxlen, outbuf);
|
399
|
+
}
|
400
|
+
if (ptr->recv_count == 0) {
|
401
|
+
istat = MPI_Recv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
|
402
|
+
0, MPI_COMM_WORLD, &status);
|
403
|
+
if (istat != MPI_SUCCESS) {
|
404
|
+
rb_raise(rb_eStandardError,"MPI_recv failed with status=%d\n",istat);
|
405
|
+
}
|
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
|
+
}
|
411
|
+
}
|
412
|
+
MPI_Get_count(&status, MPI_CHAR, &count);
|
413
|
+
ptr->recv_count = count;
|
414
|
+
return mp_substr(ptr, maxlen, outbuf);
|
415
|
+
}
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
static void
|
420
|
+
request_irecv(struct MPipe *ptr)
|
421
|
+
{
|
422
|
+
int istat;
|
423
|
+
|
424
|
+
if (ptr->recv_count == 0) {
|
425
|
+
istat = MPI_Irecv(ptr->recv_buffer, mp_buffer_size, MPI_CHAR, ptr->rank,
|
426
|
+
0, MPI_COMM_WORLD, &ptr->recv_request);
|
427
|
+
if (istat != MPI_SUCCESS) {
|
428
|
+
rb_raise(rb_eStandardError,"MPI_Irecv failed with status=%d",istat);
|
429
|
+
}
|
430
|
+
ptr->recv_count = -1; // requesting
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
/*
|
435
|
+
not requesting: recv_count=0
|
436
|
+
requesting: recv_count=-1
|
437
|
+
buffered: recv_count=n
|
438
|
+
*/
|
439
|
+
|
440
|
+
/*
|
441
|
+
* call-seq:
|
442
|
+
* mpipe.read_nonblock(integer[, outbuf [, opts]]) -> string
|
443
|
+
*
|
444
|
+
* Similar to #read, but raises +EOFError+ at end of string unless the
|
445
|
+
* +exception: false+ option is passed in.
|
446
|
+
*/
|
447
|
+
static VALUE
|
448
|
+
mp_read_nonblock(int argc, VALUE *argv, VALUE self)
|
449
|
+
{
|
450
|
+
struct MPipe *ptr = MPipe(self);
|
451
|
+
MPI_Status status;
|
452
|
+
int istat;
|
453
|
+
int count;
|
454
|
+
int complete = 0;
|
455
|
+
VALUE maxlen = Qnil;
|
456
|
+
VALUE outbuf = Qnil;
|
457
|
+
VALUE opts = Qnil;
|
458
|
+
VALUE val;
|
459
|
+
|
460
|
+
rb_scan_args(argc, argv, "02:", &maxlen, &outbuf, &opts);
|
461
|
+
|
462
|
+
if (ptr->recv_count > 0) {
|
463
|
+
return mp_substr(ptr, maxlen, outbuf);
|
464
|
+
}
|
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);
|
469
|
+
}
|
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");
|
480
|
+
}
|
481
|
+
}
|
482
|
+
return val;
|
483
|
+
}
|
484
|
+
|
485
|
+
static VALUE
|
486
|
+
mp_s_select(int argc, VALUE *argv, VALUE mod)
|
487
|
+
{
|
488
|
+
struct MPipe *ptr;
|
489
|
+
MPI_Request *ary_of_requests;
|
490
|
+
int *ary_of_indices;
|
491
|
+
MPI_Status *ary_of_statuses;
|
492
|
+
int incount, outcount;
|
493
|
+
int i, count, istat;
|
494
|
+
VALUE rd_ary, result_ary, item;
|
495
|
+
|
496
|
+
if (argc==0) {
|
497
|
+
rb_raise(rb_eArgError, "no argument");
|
498
|
+
}
|
499
|
+
incount = RARRAY_LEN(argv[0]);
|
500
|
+
|
501
|
+
result_ary = rb_ary_new();
|
502
|
+
rd_ary = rb_ary_new();
|
503
|
+
rb_ary_push(result_ary, rd_ary);
|
504
|
+
for (i=0; i < incount; i++) {
|
505
|
+
item = RARRAY_AREF(argv[0], i);
|
506
|
+
ptr = MPipe(item);
|
507
|
+
if (ptr->recv_count > 0) {
|
508
|
+
rb_ary_push(rd_ary, item);
|
509
|
+
}
|
510
|
+
}
|
511
|
+
if (RARRAY_LEN(rd_ary) > 0) {
|
512
|
+
return result_ary;
|
513
|
+
}
|
514
|
+
|
515
|
+
ary_of_requests = ALLOCA_N(MPI_Request, incount);
|
516
|
+
ary_of_statuses = ALLOCA_N(MPI_Status, incount);
|
517
|
+
ary_of_indices = ALLOCA_N(int, incount);
|
518
|
+
|
519
|
+
for (i=0; i < incount; i++) {
|
520
|
+
item = RARRAY_AREF(argv[0], i);
|
521
|
+
ptr = MPipe(item);
|
522
|
+
request_irecv(ptr);
|
523
|
+
ary_of_requests[i] = ptr->recv_request;
|
524
|
+
}
|
525
|
+
|
526
|
+
istat = MPI_Waitsome(incount, ary_of_requests,
|
527
|
+
&outcount, ary_of_indices, ary_of_statuses);
|
528
|
+
if (istat != MPI_SUCCESS) {
|
529
|
+
rb_raise(rb_eStandardError,"MPI_Waitany failed with status=%d",istat);
|
530
|
+
}
|
531
|
+
|
532
|
+
for (i=0; i < outcount; i++) {
|
533
|
+
item = RARRAY_AREF(argv[0], ary_of_indices[i]);
|
534
|
+
MPI_Get_count(&ary_of_statuses[i], MPI_BYTE, &count);
|
535
|
+
ptr = MPipe(item);
|
536
|
+
ptr->recv_count = count;
|
537
|
+
rb_ary_push(rd_ary, item);
|
538
|
+
}
|
539
|
+
return result_ary;
|
540
|
+
}
|
541
|
+
|
542
|
+
|
543
|
+
void Init_mpipe()
|
544
|
+
{
|
545
|
+
VALUE cMPipe, mComm;
|
546
|
+
|
547
|
+
cMPipe = rb_define_class("MPipe", rb_cData);
|
548
|
+
|
549
|
+
// MPI
|
550
|
+
rb_define_module_function(cMPipe, "init", mp_mpi_init, -1);
|
551
|
+
rb_define_module_function(cMPipe, "finalize", mp_mpi_finalize, 0);
|
552
|
+
rb_define_module_function(cMPipe, "abort", mp_mpi_abort, 1);
|
553
|
+
rb_define_module_function(cMPipe, "buffer_size", mp_mpi_buffer_size, 0);
|
554
|
+
rb_define_module_function(cMPipe, "buffer_size=", mp_mpi_set_buffer_size, 1);
|
555
|
+
|
556
|
+
rb_define_const(cMPipe, "VERSION", rb_str_new2(MPIPE_VERSION));
|
557
|
+
rb_define_const(cMPipe, "MPI_VERSION", INT2NUM(MPI_VERSION));
|
558
|
+
rb_define_const(cMPipe, "MPI_SUBVERSION", INT2NUM(MPI_SUBVERSION));
|
559
|
+
rb_define_const(cMPipe, "SUCCESS", INT2NUM(MPI_SUCCESS));
|
560
|
+
rb_define_const(cMPipe, "PROC_NULL", INT2NUM(MPI_PROC_NULL));
|
561
|
+
|
562
|
+
// MPI::Comm
|
563
|
+
mComm = rb_define_module_under(cMPipe, "Comm");
|
564
|
+
rb_define_module_function(mComm, "rank", mp_comm_rank, 0);
|
565
|
+
rb_define_module_function(mComm, "size", mp_comm_size, 0);
|
566
|
+
|
567
|
+
//rb_include_module(cMPipe, rb_mEnumerable);
|
568
|
+
rb_define_alloc_func(cMPipe, mp_s_allocate);
|
569
|
+
rb_define_singleton_method(cMPipe, "new", mp_s_new, 1);
|
570
|
+
rb_define_method(cMPipe, "initialize", mp_initialize, 1);
|
571
|
+
|
572
|
+
rb_define_method(cMPipe, "write", mp_write, 1);
|
573
|
+
rb_define_method(cMPipe, "write_nonblock", mp_write, 1);
|
574
|
+
rb_define_method(cMPipe, "print", mp_write, 1);
|
575
|
+
rb_define_method(cMPipe, "read", mp_read, -1);
|
576
|
+
rb_define_method(cMPipe, "read_nonblock", mp_read_nonblock, -1);
|
577
|
+
rb_define_method(cMPipe, "close", mp_close, 1);
|
578
|
+
|
579
|
+
rb_define_singleton_method(cMPipe, "select", mp_s_select, -1);
|
580
|
+
|
581
|
+
sym_exception = ID2SYM(rb_intern("exception"));
|
582
|
+
id_allocated_mpipe = rb_intern("allocated_mpipe");
|
583
|
+
eEAGAINWaitReadable = rb_const_get(rb_cIO, rb_intern("EWOULDBLOCKWaitReadable"));
|
584
|
+
}
|