parallelQueue 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -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