parallelpipes 1.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/parallelpipes.rb +89 -4
- metadata +23 -7
data/lib/parallelpipes.rb
CHANGED
@@ -30,10 +30,24 @@
|
|
30
30
|
# These processes are separate operating system processes; thus, Parallel Pipes enables genuine (and easy) parallelization in Ruby Programs.
|
31
31
|
#
|
32
32
|
#
|
33
|
-
# A Parallel Pipe has
|
34
|
-
# 1. <b>
|
35
|
-
# 2. <b>
|
36
|
-
#
|
33
|
+
# A Parallel Pipe has three distinct philosophies of use:
|
34
|
+
# 1. <b>Parallel Iterators</b> This is a new addition; it adds parallel iterators to Enumerable, so iterations can automatically be done on multiple cores.
|
35
|
+
# 2. <b>Simple MPI:</b> Allows creating of new parallel processes and synchronous and asynchronous messaging passing between them.
|
36
|
+
# 3. <b>Using a Controller</b>: Allows messaging passing, and also blocking synchronization (mutexes), and controlled access to shared resources, with automatic loading and saving of those resources.
|
37
|
+
#
|
38
|
+
#
|
39
|
+
# === Parallel Iterators
|
40
|
+
#
|
41
|
+
# See Enumerable
|
42
|
+
#
|
43
|
+
# Eg.
|
44
|
+
#
|
45
|
+
# arr = [0.3, 0.5, 0.89] # Any array or any object that mixes in Enumerable
|
46
|
+
#
|
47
|
+
# output = arr.parallel_map do |element|
|
48
|
+
# large_calculation(element)
|
49
|
+
# end
|
50
|
+
#
|
37
51
|
# === Simple MPI
|
38
52
|
#
|
39
53
|
# This approach will be familiar to anyone who uses MPI proper. New processes can be created by forking and messages can be passed between them. Any message contents are acceptable where <tt>eval(contents.inspect) == contents</tt>. Messages can be sent and received both synchronously and asynchronously.
|
@@ -2316,6 +2330,77 @@ class PPipe
|
|
2316
2330
|
|
2317
2331
|
end
|
2318
2332
|
|
2333
|
+
module Kernel
|
2334
|
+
# Returns the number of processor for Linux, OS X or Windows.
|
2335
|
+
def number_of_processors_for_parallel_map
|
2336
|
+
if RUBY_PLATFORM =~ /linux/
|
2337
|
+
return `cat /proc/cpuinfo | grep processor | wc -l`.to_i
|
2338
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
2339
|
+
return `sysctl -n hw.logicalcpu`.to_i
|
2340
|
+
elsif RUBY_PLATFORM =~ /win32/
|
2341
|
+
# this works for windows 2000 or greater
|
2342
|
+
require 'win32ole'
|
2343
|
+
wmi = WIN32OLE.connect("winmgmts://")
|
2344
|
+
wmi.ExecQuery("select * from Win32_ComputerSystem").each do |system|
|
2345
|
+
begin
|
2346
|
+
processors = system.NumberOfLogicalProcessors
|
2347
|
+
rescue
|
2348
|
+
processors = 0
|
2349
|
+
end
|
2350
|
+
return [system.NumberOfProcessors, processors].max
|
2351
|
+
end
|
2352
|
+
end
|
2353
|
+
raise "can't determine 'number_of_processors' for '#{RUBY_PLATFORM}'"
|
2354
|
+
end
|
2355
|
+
end
|
2356
|
+
module Enumerable
|
2357
|
+
|
2358
|
+
# Parallel Iterator: Use in exactly the same way as map. The last argument is a hash of options. n_procs can be supplied as an option (defaults to number of CPUs).
|
2359
|
+
# Eg.
|
2360
|
+
#
|
2361
|
+
# arr = [0.3, 0.5, 0.89] # Any array or any object that mixes in Enumerable
|
2362
|
+
#
|
2363
|
+
# output = Array.parallel_map do |element|
|
2364
|
+
# large_calculation(element)
|
2365
|
+
# end
|
2366
|
+
#
|
2367
|
+
# Or
|
2368
|
+
#
|
2369
|
+
# output = Array.parallel_map(n_procs: 4) do |element|
|
2370
|
+
# large_calculation(element)
|
2371
|
+
# end
|
2372
|
+
|
2373
|
+
|
2374
|
+
def parallel_map(*args, &block)
|
2375
|
+
ncpus = number_of_processors_for_parallel_map
|
2376
|
+
if args[-1].class == Hash
|
2377
|
+
options = args.pop
|
2378
|
+
ncpus = options[:n_procs] if options[:n_procs]
|
2379
|
+
end
|
2380
|
+
|
2381
|
+
ppipe = PPipe.new(ncpus, false)
|
2382
|
+
ppipe.fork(ncpus-1)
|
2383
|
+
i = -1
|
2384
|
+
each(*args) do |*yargs|
|
2385
|
+
# $stderr.puts i, ppipe.mpn
|
2386
|
+
i+=1
|
2387
|
+
next unless i%ncpus == ppipe.mpn
|
2388
|
+
value = block.call(*yargs)
|
2389
|
+
# $stderr.puts value
|
2390
|
+
ppipe.i_send(i, Marshal.dump(value), tp: 0)
|
2391
|
+
|
2392
|
+
end
|
2393
|
+
(ppipe.die; exit) unless ppipe.is_root
|
2394
|
+
ppipe.waitall
|
2395
|
+
i = 0
|
2396
|
+
map(*args) do |*yargs|
|
2397
|
+
value = Marshal.load(ppipe.w_recv(i))
|
2398
|
+
i+=1
|
2399
|
+
value
|
2400
|
+
end
|
2401
|
+
end
|
2402
|
+
end
|
2403
|
+
|
2319
2404
|
|
2320
2405
|
|
2321
2406
|
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallelpipes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Edmund Highcock
|
@@ -9,11 +15,11 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-12 00:00:00 +01:00
|
13
19
|
default_executable:
|
14
20
|
dependencies: []
|
15
21
|
|
16
|
-
description: Parallel Pipes is a simple, easy to use, MPI-like implentation for Ruby, allowing you to create and send messages between multiple ruby processes and allowing your code to run on multiple processors.
|
22
|
+
description: Parallel Pipes is a simple, easy to use, MPI-like implentation for Ruby, allowing you to create and send messages between multiple ruby processes and allowing your code to run on multiple processors. Also provides parallel iterators.
|
17
23
|
email:
|
18
24
|
executables: []
|
19
25
|
|
@@ -25,29 +31,39 @@ files:
|
|
25
31
|
- lib/parallelpipes.rb
|
26
32
|
has_rdoc: true
|
27
33
|
homepage: http://parallelpipes.rubyforge.org/
|
34
|
+
licenses: []
|
35
|
+
|
28
36
|
post_install_message:
|
29
37
|
rdoc_options: []
|
30
38
|
|
31
39
|
require_paths:
|
32
40
|
- lib
|
33
41
|
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
34
43
|
requirements:
|
35
44
|
- - ">="
|
36
45
|
- !ruby/object:Gem::Version
|
46
|
+
hash: 51
|
47
|
+
segments:
|
48
|
+
- 1
|
49
|
+
- 9
|
50
|
+
- 0
|
37
51
|
version: 1.9.0
|
38
|
-
version:
|
39
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
40
54
|
requirements:
|
41
55
|
- - ">="
|
42
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
43
60
|
version: "0"
|
44
|
-
version:
|
45
61
|
requirements: []
|
46
62
|
|
47
63
|
rubyforge_project: parallelpipes
|
48
|
-
rubygems_version: 1.3.
|
64
|
+
rubygems_version: 1.3.7
|
49
65
|
signing_key:
|
50
|
-
specification_version:
|
66
|
+
specification_version: 3
|
51
67
|
summary: MPI-like Parallel Processing Implementation for Ruby
|
52
68
|
test_files: []
|
53
69
|
|