parallelize 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +1 -5
- data/README.markdown +67 -0
- data/Rakefile +8 -7
- data/VERSION +1 -1
- data/lib/parallelize.rb +1 -1
- data/lib/parallelize/enumerable_ext.rb +63 -44
- data/test/test_parallelize.rb +10 -0
- metadata +76 -93
- data/README.rdoc +0 -52
data/CHANGELOG.rdoc
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,9 +6,7 @@ GEM
|
|
6
6
|
bundler (~> 1.0)
|
7
7
|
git (>= 1.2.5)
|
8
8
|
rake
|
9
|
-
rake (0.9.2)
|
10
|
-
rcov (0.9.9)
|
11
|
-
rcov (0.9.9-java)
|
9
|
+
rake (0.9.2.2)
|
12
10
|
yard (0.6.8)
|
13
11
|
|
14
12
|
PLATFORMS
|
@@ -16,7 +14,5 @@ PLATFORMS
|
|
16
14
|
ruby
|
17
15
|
|
18
16
|
DEPENDENCIES
|
19
|
-
bundler (~> 1.0.0)
|
20
17
|
jeweler (~> 1.6.4)
|
21
|
-
rcov
|
22
18
|
yard (~> 0.6.0)
|
data/README.markdown
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# parallelize
|
2
|
+
|
3
|
+
Simple multi-threading for Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
```
|
7
|
+
gem install parallelize
|
8
|
+
```
|
9
|
+
|
10
|
+
## Examples
|
11
|
+
```ruby
|
12
|
+
require 'rubygems'
|
13
|
+
require 'parallelize'
|
14
|
+
|
15
|
+
parallelize(4) do
|
16
|
+
puts "I'm a thread"
|
17
|
+
|
18
|
+
# ...
|
19
|
+
end
|
20
|
+
|
21
|
+
# Zero-based thread index
|
22
|
+
parallelize(4) do |thread_idx|
|
23
|
+
puts "I'm thread ##{thread_idx}"
|
24
|
+
|
25
|
+
# ...
|
26
|
+
end
|
27
|
+
|
28
|
+
# Enumerable#peach
|
29
|
+
(0..100).peach(4) do |elem, thread_idx|
|
30
|
+
puts "Thread ##{thread_idx} processing #{elem}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Enumerable#pmap
|
34
|
+
(0..100).pmap(4) do |elem|
|
35
|
+
elem ** 2
|
36
|
+
end
|
37
|
+
|
38
|
+
(0..100).pmap(8) do |elem, thread_idx|
|
39
|
+
elem * thread_idx
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
### Collecting exceptions
|
44
|
+
```ruby
|
45
|
+
begin
|
46
|
+
parallelize(4, true) do |elem, thread_idx|
|
47
|
+
# Each thread can complete its block even when some other threads throw exceptions
|
48
|
+
end
|
49
|
+
rescue ParallelException => e
|
50
|
+
p e.exceptions
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
## Contributing to parallelize
|
55
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
56
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
57
|
+
* Fork the project
|
58
|
+
* Start a feature/bugfix branch
|
59
|
+
* Commit and push until you are happy with your contribution
|
60
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
61
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
62
|
+
|
63
|
+
## Copyright
|
64
|
+
|
65
|
+
Copyright (c) 2011 Junegunn Choi. See LICENSE.txt for
|
66
|
+
further details.
|
67
|
+
|
data/Rakefile
CHANGED
@@ -32,13 +32,14 @@ Rake::TestTask.new(:test) do |test|
|
|
32
32
|
test.verbose = true
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
test.
|
39
|
-
test.
|
40
|
-
test.
|
41
|
-
|
35
|
+
# TODO: simplecov
|
36
|
+
#require 'rcov/rcovtask'
|
37
|
+
#Rcov::RcovTask.new do |test|
|
38
|
+
# test.libs << 'test'
|
39
|
+
# test.pattern = 'test/**/test_*.rb'
|
40
|
+
# test.verbose = true
|
41
|
+
# test.rcov_opts << '--exclude "gems/*"'
|
42
|
+
#end
|
42
43
|
|
43
44
|
task :default => :test
|
44
45
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/parallelize.rb
CHANGED
@@ -6,6 +6,6 @@ require 'parallelize/enumerable_ext'
|
|
6
6
|
# @param [Fixnum] num_threads Number of concurrent threads
|
7
7
|
# @param [Boolean] collect_exceptions If true, waits for all threads to complete even in case of exception, and throws ParallelException at the end. If false exception is immediately thrown.
|
8
8
|
def parallelize num_threads, collect_exceptions = false, &block
|
9
|
-
num_threads.times.
|
9
|
+
num_threads.times.peach(num_threads, collect_exceptions, &block)
|
10
10
|
end
|
11
11
|
|
@@ -1,53 +1,72 @@
|
|
1
1
|
module Enumerable
|
2
|
+
module Parallelize
|
3
|
+
def self.it enum, num_threads, method, collect_exceptions, &block
|
4
|
+
raise ArgumentError.new("Block not given") unless block_given?
|
5
|
+
raise ArgumentError.new("Invalid number of threads") if num_threads < 1
|
6
|
+
|
7
|
+
threads = []
|
8
|
+
enum.each_slice((enum.count{true} / num_threads.to_f).ceil) do |slice|
|
9
|
+
threads <<
|
10
|
+
case block.arity
|
11
|
+
when 2
|
12
|
+
Thread.new(slice, threads.length) { |my_slice, thread_idx|
|
13
|
+
my_slice.send(method) { |e| yield e, thread_idx }
|
14
|
+
}
|
15
|
+
when 1
|
16
|
+
Thread.new(slice) { |my_slice|
|
17
|
+
my_slice.send(method) { |e| yield e }
|
18
|
+
}
|
19
|
+
when 0, -1
|
20
|
+
raise ArgumentError.new("Invalid arity: #{block.arity}") if
|
21
|
+
RUBY_VERSION !~ /^1.8\./ && block.arity == -1
|
22
|
+
Thread.new(slice) { |my_slice|
|
23
|
+
my_slice.send(method) { yield }
|
24
|
+
}
|
25
|
+
else
|
26
|
+
raise ArgumentError.new("Invalid arity: #{block.arity}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
exceptions = {}
|
31
|
+
threads.each_with_index do |thr, idx|
|
32
|
+
begin
|
33
|
+
thr.join
|
34
|
+
rescue Exception => e
|
35
|
+
if collect_exceptions
|
36
|
+
exceptions[idx] = e
|
37
|
+
nil
|
38
|
+
else
|
39
|
+
raise e
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
unless exceptions.empty?
|
45
|
+
raise ParallelException.new(exceptions)
|
46
|
+
end
|
47
|
+
|
48
|
+
if method == :each
|
49
|
+
threads
|
50
|
+
elsif method == :map
|
51
|
+
threads.map(&:value).inject(:+)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
2
56
|
# Divides the Enumerable objects into pieces and execute with multiple threads
|
3
57
|
# @return [Array] Threads.
|
4
58
|
# @param [Fixnum] num_threads Number of concurrent threads
|
5
59
|
# @param [Boolean] collect_exceptions If true, waits for all threads to complete even in case of exception, and throws ParallelException at the end. If false exception is immediately thrown.
|
6
60
|
def peach num_threads, collect_exceptions = false, &block
|
7
|
-
|
8
|
-
|
61
|
+
Parallelize.it self, num_threads, :each, collect_exceptions, &block
|
62
|
+
end
|
9
63
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
}
|
18
|
-
when 1
|
19
|
-
Thread.new(slice) { |my_slice|
|
20
|
-
my_slice.each { |e| yield e }
|
21
|
-
}
|
22
|
-
when 0, -1
|
23
|
-
raise ArgumentError.new("Invalid arity: #{block.arity}") if
|
24
|
-
RUBY_VERSION !~ /^1.8\./ && block.arity == -1
|
25
|
-
Thread.new(slice) { |my_slice|
|
26
|
-
my_slice.each { yield }
|
27
|
-
}
|
28
|
-
else
|
29
|
-
raise ArgumentError.new("Invalid arity: #{block.arity}")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
exceptions = {}
|
34
|
-
threads.each_with_index do |thr, idx|
|
35
|
-
begin
|
36
|
-
thr.join
|
37
|
-
rescue Exception => e
|
38
|
-
if collect_exceptions
|
39
|
-
exceptions[idx] = e
|
40
|
-
else
|
41
|
-
raise e
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
if exceptions.empty?
|
47
|
-
threads
|
48
|
-
else
|
49
|
-
raise ParallelException.new(exceptions)
|
50
|
-
end
|
51
|
-
end
|
64
|
+
# Parallelized map.
|
65
|
+
# @return [Array] Map function output for each element
|
66
|
+
# @param [Fixnum] num_threads Number of concurrent threads
|
67
|
+
# @param [Boolean] collect_exceptions If true, waits for all threads to complete even in case of exception, and throws ParallelException at the end. If false exception is immediately thrown.
|
68
|
+
def pmap num_threads, collect_exceptions = false, &block
|
69
|
+
Parallelize.it self, num_threads, :map, collect_exceptions, &block
|
70
|
+
end
|
52
71
|
end
|
53
72
|
|
data/test/test_parallelize.rb
CHANGED
@@ -127,4 +127,14 @@ class TestParallelize < Test::Unit::TestCase
|
|
127
127
|
(0..100).peach(4) do
|
128
128
|
end
|
129
129
|
end
|
130
|
+
|
131
|
+
def test_pmap
|
132
|
+
thr = 8
|
133
|
+
n_per_thr = (101.0 / 8).ceil
|
134
|
+
i = -1
|
135
|
+
assert_equal(
|
136
|
+
(0..100).map { |e, idx| i += 1; "#{e} by #{i / n_per_thr}" },
|
137
|
+
(0..100).pmap(thr) { |e, tidx| "#{e} by #{tidx}" }
|
138
|
+
)
|
139
|
+
end
|
130
140
|
end
|
metadata
CHANGED
@@ -1,114 +1,97 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallelize
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.1
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
7
|
+
authors:
|
8
|
+
- Junegunn Choi
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
prerelease: false
|
47
|
-
type: :development
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: rcov
|
50
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: "0"
|
56
|
-
requirement: *id004
|
57
|
-
prerelease: false
|
58
|
-
type: :development
|
12
|
+
date: 2012-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: yard
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.6.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.6.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: jeweler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.6.4
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.6.4
|
59
46
|
description: Simple multi-threading for Ruby
|
60
47
|
email: junegunn.c@gmail.com
|
61
48
|
executables: []
|
62
|
-
|
63
49
|
extensions: []
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
50
|
+
extra_rdoc_files:
|
51
|
+
- LICENSE.txt
|
52
|
+
- README.markdown
|
53
|
+
files:
|
54
|
+
- .document
|
55
|
+
- CHANGELOG.rdoc
|
56
|
+
- Gemfile
|
57
|
+
- Gemfile.lock
|
58
|
+
- LICENSE.txt
|
59
|
+
- README.markdown
|
60
|
+
- Rakefile
|
61
|
+
- VERSION
|
62
|
+
- example/example.rb
|
63
|
+
- example/example2.rb
|
64
|
+
- lib/parallelize.rb
|
65
|
+
- lib/parallelize/enumerable_ext.rb
|
66
|
+
- lib/parallelize/parallel_exception.rb
|
67
|
+
- test/helper.rb
|
68
|
+
- test/test_parallelize.rb
|
83
69
|
homepage: http://github.com/junegunn/parallelize
|
84
|
-
licenses:
|
85
|
-
|
70
|
+
licenses:
|
71
|
+
- MIT
|
86
72
|
post_install_message:
|
87
73
|
rdoc_options: []
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
77
|
none: false
|
93
|
-
requirements:
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
hash: 4037532998974082938
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
86
|
none: false
|
102
|
-
requirements:
|
103
|
-
|
104
|
-
|
105
|
-
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
106
91
|
requirements: []
|
107
|
-
|
108
92
|
rubyforge_project:
|
109
|
-
rubygems_version: 1.8.
|
93
|
+
rubygems_version: 1.8.24
|
110
94
|
signing_key:
|
111
95
|
specification_version: 3
|
112
96
|
summary: Simple multi-threading for Ruby
|
113
97
|
test_files: []
|
114
|
-
|
data/README.rdoc
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
= parallelize
|
2
|
-
|
3
|
-
Simple multi-threading for Ruby.
|
4
|
-
|
5
|
-
== Installation
|
6
|
-
gem install parallelize
|
7
|
-
|
8
|
-
== Examples
|
9
|
-
require 'rubygems'
|
10
|
-
require 'parallelize'
|
11
|
-
|
12
|
-
parallelize(4) do
|
13
|
-
puts "I'm a thread"
|
14
|
-
|
15
|
-
# ...
|
16
|
-
end
|
17
|
-
|
18
|
-
# Zero-based thread index
|
19
|
-
parallelize(4) do |thread_idx|
|
20
|
-
puts "I'm thread ##{thread_idx}"
|
21
|
-
|
22
|
-
# ...
|
23
|
-
end
|
24
|
-
|
25
|
-
# Enumerable#peach
|
26
|
-
(0..100).peach(4) do |elem, thread_idx|
|
27
|
-
puts "Thread ##{thread_idx} processing #{elem}"
|
28
|
-
end
|
29
|
-
|
30
|
-
=== Collecting exceptions
|
31
|
-
begin
|
32
|
-
parallelize(4, true) do |elem, thread_idx|
|
33
|
-
# Each thread can complete its block even when some other threads throw exceptions
|
34
|
-
end
|
35
|
-
rescue ParallelException => e
|
36
|
-
p e.exceptions
|
37
|
-
end
|
38
|
-
|
39
|
-
== Contributing to parallelize
|
40
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
41
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
42
|
-
* Fork the project
|
43
|
-
* Start a feature/bugfix branch
|
44
|
-
* Commit and push until you are happy with your contribution
|
45
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
46
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
47
|
-
|
48
|
-
== Copyright
|
49
|
-
|
50
|
-
Copyright (c) 2011 Junegunn Choi. See LICENSE.txt for
|
51
|
-
further details.
|
52
|
-
|