parallelpipes 1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/parallelpipes.rb +89 -4
  2. metadata +23 -7
@@ -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 two distinct philosophies of use:
34
- # 1. <b>Simple MPI:</b> Allows creating of new parallel processes and synchronous and asynchronous messaging passing between them.
35
- # 2. <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.
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
- version: "1.0"
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-11 00:00:00 +01:00
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.1
64
+ rubygems_version: 1.3.7
49
65
  signing_key:
50
- specification_version: 2
66
+ specification_version: 3
51
67
  summary: MPI-like Parallel Processing Implementation for Ruby
52
68
  test_files: []
53
69