grosser-parallel 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.
data/README.markdown CHANGED
@@ -8,22 +8,50 @@ Install
8
8
 
9
9
  Usage
10
10
  =====
11
+ ### Processes
12
+ - Speedup through multiple cpus
13
+ - Speedup for blocking operations
14
+ - Protects global data
15
+ - Extra memory used
11
16
 
12
- #i -> 0..number_of_your_cpus
17
+ ### Threads
18
+ - Speedup for blocking operations
19
+ - Global data can be modified
20
+ - No extra memory used
21
+
22
+ Map-Reduce-Style
23
+ # 2 Cpus -> finished after 2 runs (a,b + c)
24
+ results = Parallel.map(['a','b','c']) do |one_letter|
25
+ expensive_calculation(letter)
26
+ end
27
+
28
+ # 3 Processes -> finished after 1 run
29
+ results = Parallel.map(['a','b','c'], :in_processes=>3){|one_letter| ... }
30
+
31
+ # 3 Threads -> finished after 1 run
32
+ results = Parallel.map(['a','b','c'], :in_threads=>3){|one_letter| ... }
33
+
34
+
35
+ Normal
36
+ #i -> 0...number_of_your_cpus
13
37
  results = Parallel.in_processes do |i|
14
38
  expensive_computation(data[i])
15
39
  end
16
40
 
17
- #i -> 0..4
41
+ #i -> 0...4
18
42
  results = Parallel.in_processes(4) do |i|
19
43
  expensive_computation(data[i])
20
44
  end
21
45
 
22
- #same with threads (no speedup through multiple cpus, but speedup for blocking operations)
46
+ # Threads
23
47
  results = Parallel.in_threads(4) do |i|
24
48
  blocking_computation(data[i])
25
49
  end
26
50
 
51
+ TODO
52
+ ====
53
+ - optimize Parallel.map by not waiting for a group to finish: start new when one process finishes
54
+
27
55
  Author
28
56
  ======
29
57
  [Michael Grosser](http://pragmatig.wordpress.com)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/lib/parallel.rb CHANGED
@@ -49,6 +49,24 @@ class Parallel
49
49
  out.map{|x| Marshal.load(x)} #deserialize
50
50
  end
51
51
 
52
+ def self.map(array, options={})
53
+ count = if options[:in_threads]
54
+ method = 'in_threads'
55
+ options[:in_threads]
56
+ else
57
+ method = 'in_processes'
58
+ options[:in_processes] || processor_count
59
+ end
60
+
61
+ results = []
62
+ in_groups_of(array, count).each do |group|
63
+ results += send(method, group.size) do |i|
64
+ yield group[i]
65
+ end
66
+ end
67
+ results
68
+ end
69
+
52
70
  def self.processor_count
53
71
  case RUBY_PLATFORM
54
72
  when /darwin/
@@ -60,6 +78,19 @@ class Parallel
60
78
 
61
79
  private
62
80
 
81
+ def self.in_groups_of(array, count)
82
+ results = []
83
+ loop do
84
+ slice = array[(results.size * count)...((results.size+1) * count)]
85
+ if slice.nil? or slice.empty?
86
+ break
87
+ else
88
+ results << slice
89
+ end
90
+ end
91
+ results
92
+ end
93
+
63
94
  #handle user interrup (Ctrl+c)
64
95
  def self.kill_on_ctrl_c(pids)
65
96
  Signal.trap 'SIGINT' do
data/parallel.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{parallel}
5
- s.version = "0.2.0"
5
+ s.version = "0.3.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Michael Grosser"]
9
- s.date = %q{2009-08-13}
9
+ s.date = %q{2009-08-26}
10
10
  s.email = %q{grosser.michael@gmail.com}
11
11
  s.extra_rdoc_files = [
12
12
  "README.markdown"
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
18
18
  "lib/parallel.rb",
19
19
  "parallel.gemspec",
20
20
  "spec/cases/parallel_influence_outside_data.rb",
21
+ "spec/cases/parallel_map.rb",
22
+ "spec/cases/parallel_map_sleeping.rb",
21
23
  "spec/cases/parallel_sleeping_2.rb",
22
24
  "spec/cases/parallel_start_and_kill.rb",
23
25
  "spec/cases/parallel_with_detected_cpus.rb",
@@ -37,7 +39,9 @@ Gem::Specification.new do |s|
37
39
  "spec/cases/parallel_start_and_kill.rb",
38
40
  "spec/cases/parallel_with_set_processes.rb",
39
41
  "spec/cases/parallel_influence_outside_data.rb",
40
- "spec/cases/parallel_with_detected_cpus.rb"
42
+ "spec/cases/parallel_map_sleeping.rb",
43
+ "spec/cases/parallel_with_detected_cpus.rb",
44
+ "spec/cases/parallel_map.rb"
41
45
  ]
42
46
 
43
47
  if s.respond_to? :specification_version then
@@ -0,0 +1,6 @@
1
+ require 'spec/spec_helper.rb'
2
+
3
+ result = Parallel.map(['a','b','c','d']) do |x|
4
+ "-#{x}-"
5
+ end
6
+ print result * ' '
@@ -0,0 +1,5 @@
1
+ require 'spec/spec_helper.rb'
2
+
3
+ Parallel.map(['a','b','c','d']) do |x|
4
+ sleep 1
5
+ end
@@ -54,4 +54,42 @@ describe Parallel do
54
54
  Parallel.in_threads(4){|i| "XXX#{i}"}.should == ["XXX0",'XXX1','XXX2','XXX3']
55
55
  end
56
56
  end
57
+
58
+ describe :map do
59
+ it "saves time" do
60
+ t = Time.now
61
+ `ruby spec/cases/parallel_map_sleeping.rb`
62
+ Time.now.should be_close(t, 3)
63
+ end
64
+
65
+ it "executes with given parameters" do
66
+ `ruby spec/cases/parallel_map.rb`.should == "-a- -b- -c- -d-"
67
+ end
68
+
69
+ it "does not flatten results" do
70
+ Parallel.map([1,2,3], :in_threads=>2){|x| [x,x]}.should == [[1,1],[2,2],[3,3]]
71
+ end
72
+
73
+ it "can run in threads" do
74
+ Parallel.map([1,2,3,4,5,6,7,8,9], :in_threads=>4){|x| x+2 }.should == [3,4,5,6,7,8,9,10,11]
75
+ end
76
+ end
77
+
78
+ describe :in_groups_of do
79
+ it "works for empty" do
80
+ Parallel.send(:in_groups_of, [], 3).should == []
81
+ end
82
+
83
+ it "works for smaller then count" do
84
+ Parallel.send(:in_groups_of, [1,2], 3).should == [[1,2]]
85
+ end
86
+
87
+ it "works for count" do
88
+ Parallel.send(:in_groups_of, [1,2,3], 3).should == [[1,2,3]]
89
+ end
90
+
91
+ it "works for larger than count" do
92
+ Parallel.send(:in_groups_of, [1,2,3,4], 3).should == [[1,2,3],[4]]
93
+ end
94
+ end
57
95
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grosser-parallel
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
  - Michael Grosser
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-13 00:00:00 -07:00
12
+ date: 2009-08-26 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -28,6 +28,8 @@ files:
28
28
  - lib/parallel.rb
29
29
  - parallel.gemspec
30
30
  - spec/cases/parallel_influence_outside_data.rb
31
+ - spec/cases/parallel_map.rb
32
+ - spec/cases/parallel_map_sleeping.rb
31
33
  - spec/cases/parallel_sleeping_2.rb
32
34
  - spec/cases/parallel_start_and_kill.rb
33
35
  - spec/cases/parallel_with_detected_cpus.rb
@@ -36,7 +38,6 @@ files:
36
38
  - spec/spec_helper.rb
37
39
  has_rdoc: false
38
40
  homepage: http://github.com/grosser/parallel
39
- licenses:
40
41
  post_install_message:
41
42
  rdoc_options:
42
43
  - --charset=UTF-8
@@ -57,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
58
  requirements: []
58
59
 
59
60
  rubyforge_project:
60
- rubygems_version: 1.3.5
61
+ rubygems_version: 1.2.0
61
62
  signing_key:
62
63
  specification_version: 3
63
64
  summary: Run any kind of code in parallel processes
@@ -68,4 +69,6 @@ test_files:
68
69
  - spec/cases/parallel_start_and_kill.rb
69
70
  - spec/cases/parallel_with_set_processes.rb
70
71
  - spec/cases/parallel_influence_outside_data.rb
72
+ - spec/cases/parallel_map_sleeping.rb
71
73
  - spec/cases/parallel_with_detected_cpus.rb
74
+ - spec/cases/parallel_map.rb