parallelQueue 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +27 -0
- data/README.rdoc +111 -0
- data/gemspec.parallelQueue +22 -0
- data/lib/parallelQueue.rb +69 -0
- data/test/test_parallelQueue.rb +57 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 24af9cbe3c3f6100ad83835d65e0dd239b7fd571
|
4
|
+
data.tar.gz: 040fed41dad97007807acf19a58b05691ca9a21a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 520aaa05828f84cf4247e1367074a680c4c13207750180f4d67aa0383660bcc2ca6bf527d72d1d1dbb230ce12570258f451e1bf39b0e4613827e19ca8a4201f1
|
7
|
+
data.tar.gz: e9f8e61f9f347e326da28ff0286c356ad0f9ece706bb404ecffba87f9b2e6d014cbfa4b1263bd153e56b152ed2dcc8e57004461153cc3a90ca9f6b9b99960fe6
|
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2011-2014, Ralf Mueller (stark.dreamdetective@googlemail.com)
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* The names of its contributors may not be used to endorse or promote
|
15
|
+
products derived from this software without specific prior written
|
16
|
+
permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
= JobQueue - Let run your jobs in parallel
|
2
|
+
|
3
|
+
This package contains jobQueue:
|
4
|
+
* A simple class to parallalize your work on a user definend number of threads
|
5
|
+
* A ruby script, which uses the above class to run each line of a shell script
|
6
|
+
|
7
|
+
jobQueue can do the following things:
|
8
|
+
|
9
|
+
* Run blocks, Procs and Lambdas
|
10
|
+
* Run instance and class methods
|
11
|
+
* Run shell commands
|
12
|
+
* Respect user definded locks
|
13
|
+
|
14
|
+
I started a python2 implementation of this, which can be installed via pip
|
15
|
+
(https://pypi.python.org/pypi/jobqueue). When its maature enough, I will use
|
16
|
+
the ruby version numbers for it.
|
17
|
+
|
18
|
+
== Installation
|
19
|
+
|
20
|
+
=== Gem Installation
|
21
|
+
|
22
|
+
Download and install jobQueue with the following.
|
23
|
+
|
24
|
+
gem install jobQueue
|
25
|
+
|
26
|
+
=== Requirements
|
27
|
+
|
28
|
+
JobQueue requires Ruby only, but versions 1.9.x are needed to make use of system threads.
|
29
|
+
|
30
|
+
== Usage
|
31
|
+
|
32
|
+
=== Parallelize Ruby's blocks, procs, lambdas and things
|
33
|
+
|
34
|
+
Create a JobQueue with nThreads worker with:
|
35
|
+
|
36
|
+
jq = JobQueue.new(nThreads)
|
37
|
+
|
38
|
+
Use its push method to put in something to do
|
39
|
+
|
40
|
+
* For blocks:
|
41
|
+
jq.push do
|
42
|
+
myObject.method0(...)
|
43
|
+
myObject.method1(...)
|
44
|
+
myObject.method3(...)
|
45
|
+
end
|
46
|
+
|
47
|
+
* For procs and lambdas:
|
48
|
+
|
49
|
+
jp.push(myProc,arg0,arg1,...)
|
50
|
+
|
51
|
+
* For object methods:
|
52
|
+
|
53
|
+
jq.push([myObject,[:method,arg0,arg1,...])
|
54
|
+
|
55
|
+
* Same code can be used for class methods:
|
56
|
+
|
57
|
+
jq.push(myClass,[:myClassMethod,arg0,arg1,...])
|
58
|
+
|
59
|
+
To start the workers, call
|
60
|
+
|
61
|
+
jq.run
|
62
|
+
|
63
|
+
That's it. You might have look at tests, that come with the jobQueue gem.
|
64
|
+
|
65
|
+
=== Parallelize system commands
|
66
|
+
|
67
|
+
Use a separate class for this and push string to it:
|
68
|
+
|
69
|
+
jq = SystemJobs.new(nThreads)
|
70
|
+
jq.push('find ./src -name "*.rb"','find ./downloads -name "*.rb"')
|
71
|
+
|
72
|
+
will start 2 parallel searches for ruby files. This is implemented in the
|
73
|
+
prun.rb script, which comes with the jobQueue gem. To run each line of a shell
|
74
|
+
script on 10 threads, use:
|
75
|
+
|
76
|
+
prun.rb -j 10 jobs.sh
|
77
|
+
|
78
|
+
The '-j' switch is optional. Default is the maximum number of cores. The script
|
79
|
+
accepts multiple files and processes one after another. Try '-h' for documentation.
|
80
|
+
|
81
|
+
== Support, Issues, Bugs, ...
|
82
|
+
|
83
|
+
please use personal mail, ruby-lang mailing list or github
|
84
|
+
|
85
|
+
== Changelog
|
86
|
+
|
87
|
+
* 1.0.11: prun.rb now ignores empty lines
|
88
|
+
* 1.0.10: more flexible logging control (new switches '-l' and '-b')
|
89
|
+
* 1.0.9: print out stdout and stderr from the jobs given to prun.rb, use '-D' to avoid printing
|
90
|
+
* 1.0.8: support AIX for getting the maximum number of processors, improve processor count for jruby and rbx
|
91
|
+
|
92
|
+
== Credits
|
93
|
+
|
94
|
+
[<b>Robert Klemme</b>] For the first hints: https://www.ruby-forum.com/topic/68001#86298
|
95
|
+
|
96
|
+
== License
|
97
|
+
|
98
|
+
jobQueue use the BSD License
|
99
|
+
|
100
|
+
:include LICENSE
|
101
|
+
|
102
|
+
|
103
|
+
---
|
104
|
+
|
105
|
+
= Other stuff
|
106
|
+
|
107
|
+
Author:: Ralf Mueller <stark.dreamdetective@gmail.com>
|
108
|
+
Requires:: Ruby 1.9 or later
|
109
|
+
License:: Copyright 2011-2016 by Ralf Mueller
|
110
|
+
Released under BSD-style license. See the LICENSE
|
111
|
+
file included in the distribution.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = "parallelQueue"
|
5
|
+
s.version = '1.0.0'
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.files = ["lib/parallelQueue.rb"] + ["gemspec.parallelQueue","LICENSE","README.rdoc"]
|
8
|
+
s.description = "Extension 'parallel': Interface for pushung blocks"
|
9
|
+
s.summary = "This is a small extension to the 'parallel' library. It \
|
10
|
+
allows to push abitrary blocks to a Queue and execute them in parallel, \
|
11
|
+
whereas 'parallel' needs predefined lambdas"
|
12
|
+
s.author = "Ralf Mueller"
|
13
|
+
s.email = "stark.dreamdetective@gmail.com"
|
14
|
+
s.homepage = "https://github.com/Try2Code/jobQueue"
|
15
|
+
s.extra_rdoc_files = ["README.rdoc","LICENSE"]
|
16
|
+
s.license = "ISC" #BSD-2-Clause
|
17
|
+
s.test_file = "test/test_parallelQueue.rb"
|
18
|
+
s.required_ruby_version = ">= 1.8"
|
19
|
+
s.has_rdoc = true
|
20
|
+
end
|
21
|
+
|
22
|
+
# vim:ft=ruby
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'parallel'
|
2
|
+
# ==============================================================================
|
3
|
+
# Author: Ralf Mueller, ralf.mueller@mpimet.mpg.de
|
4
|
+
# suggestions from Robert Klemme (https://www.ruby-forum.com/topic/68001#86298)
|
5
|
+
#
|
6
|
+
# ==============================================================================
|
7
|
+
|
8
|
+
# ParallelQueue is nothing but a regular queue with the ability to store blocks
|
9
|
+
# or methods (plus aruments)
|
10
|
+
class ParallelQueue < Queue
|
11
|
+
alias :queue_push :push
|
12
|
+
include Parallel::ProcessorCount
|
13
|
+
|
14
|
+
# puts code to the queue as a
|
15
|
+
# * method: push(method,arg1,arg2,...)
|
16
|
+
# * block: push { ... }
|
17
|
+
def push (*item, &block)
|
18
|
+
queue_push(item ) unless item.empty?
|
19
|
+
queue_push([block]) unless block.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# run things with the 'parallel' library - results are returned automatically
|
23
|
+
def run(workers=processor_count)
|
24
|
+
queue_push(Parallel::Stop)
|
25
|
+
Parallel.map(self,:in_threads => workers) {|task|
|
26
|
+
if task.size > 1
|
27
|
+
if task[0].kind_of? Proc
|
28
|
+
# Expects proc/lambda with arguments,e.g.
|
29
|
+
# [mysqrt,2.789]
|
30
|
+
# [myproc,x,y,z]
|
31
|
+
task[0].call(*task[1..-1])
|
32
|
+
else
|
33
|
+
# expect an object in task[0] and one of its methods with arguments
|
34
|
+
# in task[1] as a symbol
|
35
|
+
# e.g. [a,[:attribute=,1] or
|
36
|
+
# Math,:exp,0
|
37
|
+
task[0].send(task[1],*task[2..-1])
|
38
|
+
end
|
39
|
+
else
|
40
|
+
task[0].call
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# run the given calls WITHOUT automatic result storage, but faster
|
46
|
+
def justRun(workers=processor_count)
|
47
|
+
@threads = (1..workers).map {|i|
|
48
|
+
Thread.new(self) {|q|
|
49
|
+
until ( q == ( task = q.deq ) )
|
50
|
+
if task.size > 1
|
51
|
+
if task[0].kind_of? Proc
|
52
|
+
# Expects proc/lambda with arguments, e.g. [mysqrt,2.789]
|
53
|
+
task[0].call(*task[1..-1])
|
54
|
+
else
|
55
|
+
# expect an object in task[0] and one of its methods with
|
56
|
+
# arguments in task[1] as a symbol
|
57
|
+
# e.g. [a,[:attribute=,1]
|
58
|
+
task[0].send(task[1],*task[2..-1])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
task[0].call
|
62
|
+
end
|
63
|
+
end
|
64
|
+
}
|
65
|
+
}
|
66
|
+
@threads.size.times { self.enq self}
|
67
|
+
@threads.each {|t| t.join}
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'parallel'
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__),"..","lib")
|
4
|
+
require 'parallelQueue'
|
5
|
+
|
6
|
+
class TestParallelQueue < Minitest::Test
|
7
|
+
|
8
|
+
def test_blocks
|
9
|
+
q = ParallelQueue.new
|
10
|
+
|
11
|
+
itemsA = %w[a:3:b x:55:x K:981:foo:tra]
|
12
|
+
itemsB = %w[a|5|b x|11|x K|187|foo|tra]
|
13
|
+
|
14
|
+
itemsA.each {|item|
|
15
|
+
q.push {
|
16
|
+
item.split(':')[1].to_i
|
17
|
+
}
|
18
|
+
}
|
19
|
+
itemsB.each {|item|
|
20
|
+
q.push {
|
21
|
+
item.split('|')[1].to_i
|
22
|
+
}
|
23
|
+
}
|
24
|
+
results = q.run.sort
|
25
|
+
assert_equal([3,5,11,55,187,981],results)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_procs
|
29
|
+
q = ParallelQueue.new
|
30
|
+
|
31
|
+
myProc = lambda {|r| Math.sqrt(r)}
|
32
|
+
pressure = lambda {|z|
|
33
|
+
1013.25*Math.exp((-1)*(1.602769777072154)*Math.log((Math.exp(z/10000.0)*213.15+75.0)/288.15))
|
34
|
+
}
|
35
|
+
temperature = lambda {|z|
|
36
|
+
213.0+75.0*Math.exp((-1)*z/10000.0)-273.15
|
37
|
+
}
|
38
|
+
vectorLength = lambda {|x,y,z| Math.sqrt(x*x + y*y + z*z) }
|
39
|
+
|
40
|
+
q.push(myProc,4.0)
|
41
|
+
q.push(Math,:sqrt,16.0)
|
42
|
+
[0,10,20,50,100,200,500,1000].map(&:to_f).each {|z|
|
43
|
+
q.push(pressure,z)
|
44
|
+
q.push(temperature,z)
|
45
|
+
}
|
46
|
+
q.push(Math,:sqrt,529.0)
|
47
|
+
q.push(vectorLength,0,1,0)
|
48
|
+
q.push(vectorLength,0,1,1)
|
49
|
+
q.push(vectorLength,1,1,1)
|
50
|
+
|
51
|
+
results = q.run(2).map {|f| f.round(2)}
|
52
|
+
assert_equal(
|
53
|
+
[1.0,1.41,1.73,2.0, 4.0, 7.71, 11.19, 13.36, 14.1, 14.48, 14.7, 14.78, 14.85, 23.0, 898.6, 954.56, 989.45, 1001.29, 1007.26, 1010.85, 1012.05, 1013.25],
|
54
|
+
results.sort
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parallelQueue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ralf Mueller
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: 'Extension ''parallel'': Interface for pushung blocks'
|
14
|
+
email: stark.dreamdetective@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files:
|
18
|
+
- README.rdoc
|
19
|
+
- LICENSE
|
20
|
+
files:
|
21
|
+
- LICENSE
|
22
|
+
- README.rdoc
|
23
|
+
- gemspec.parallelQueue
|
24
|
+
- lib/parallelQueue.rb
|
25
|
+
- test/test_parallelQueue.rb
|
26
|
+
homepage: https://github.com/Try2Code/jobQueue
|
27
|
+
licenses:
|
28
|
+
- ISC
|
29
|
+
metadata: {}
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '1.8'
|
39
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project:
|
46
|
+
rubygems_version: 2.5.1
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: This is a small extension to the 'parallel' library. It allows
|
50
|
+
to push abitrary blocks to a Queue and execute them in parallel, whereas
|
51
|
+
'parallel' needs predefined lambdas
|
52
|
+
test_files:
|
53
|
+
- test/test_parallelQueue.rb
|