comp_tree 0.5.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +24 -0
- data/README +19 -52
- data/Rakefile +1 -138
- data/comp_tree.gemspec +33 -30
- data/install.rb +3 -3
- data/lib/comp_tree/algorithm.rb +117 -156
- data/lib/comp_tree/driver.rb +39 -154
- data/lib/comp_tree/error.rb +18 -23
- data/lib/comp_tree/node.rb +46 -50
- data/lib/comp_tree.rb +56 -0
- data/rakelib/jumpstart/ruby.rb +51 -0
- data/{contrib/quix/lib/quix → rakelib/jumpstart}/simple_installer.rb +11 -13
- data/test/common.rb +29 -0
- data/test/test_basic.rb +189 -0
- data/test/test_circular.rb +34 -31
- data/test/test_drain.rb +38 -0
- data/test/test_exception.rb +37 -86
- data/test/test_flood.rb +14 -0
- data/test/test_grind.rb +77 -0
- data/test/test_sequential.rb +21 -0
- metadata +45 -58
- data/contrib/quix/Rakefile +0 -16
- data/contrib/quix/install.rb +0 -3
- data/contrib/quix/lib/quix/builtin/dir/casefold_brackets.rb +0 -7
- data/contrib/quix/lib/quix/builtin/kernel/tap.rb +0 -9
- data/contrib/quix/lib/quix/builtin/module/include.rb +0 -21
- data/contrib/quix/lib/quix/builtin/module/private.rb +0 -41
- data/contrib/quix/lib/quix/config.rb +0 -37
- data/contrib/quix/lib/quix/cygwin.rb +0 -60
- data/contrib/quix/lib/quix/diagnostic.rb +0 -44
- data/contrib/quix/lib/quix/enumerable.rb +0 -33
- data/contrib/quix/lib/quix/fileutils.rb +0 -37
- data/contrib/quix/lib/quix/hash_struct.rb +0 -27
- data/contrib/quix/lib/quix/kernel.rb +0 -61
- data/contrib/quix/lib/quix/lazy_struct.rb +0 -55
- data/contrib/quix/lib/quix/string.rb +0 -38
- data/contrib/quix/lib/quix/subpackager.rb +0 -52
- data/contrib/quix/lib/quix/thread_local.rb +0 -32
- data/contrib/quix/lib/quix/vars.rb +0 -138
- data/contrib/quix/lib/quix.rb +0 -32
- data/contrib/quix/test/all.rb +0 -12
- data/contrib/quix/test/test_deps.rb +0 -25
- data/contrib/quix/test/test_include.rb +0 -47
- data/contrib/quix/test/test_private.rb +0 -86
- data/contrib/quix/test/test_root.rb +0 -19
- data/contrib/quix/test/test_struct.rb +0 -48
- data/contrib/quix/test/test_vars.rb +0 -187
- data/lib/comp_tree/bucket_ipc.rb +0 -151
- data/lib/comp_tree/diagnostic.rb +0 -44
- data/lib/comp_tree/misc.rb +0 -61
- data/lib/comp_tree/retriable_fork.rb +0 -42
- data/lib/comp_tree/tap.rb +0 -9
- data/lib/comp_tree/task_node.rb +0 -22
- data/test/all.rb +0 -12
- data/test/test_bucketipc.rb +0 -72
- data/test/test_comp_tree.rb +0 -364
data/test/common.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'comp_tree'
|
5
|
+
require 'benchmark'
|
6
|
+
|
7
|
+
module TestCommon
|
8
|
+
if ARGV.include?("--bench")
|
9
|
+
def separator
|
10
|
+
puts
|
11
|
+
puts "-"*60
|
12
|
+
end
|
13
|
+
|
14
|
+
def bench_output(desc = nil, stream = STDOUT, &block)
|
15
|
+
if desc
|
16
|
+
stream.puts(desc)
|
17
|
+
end
|
18
|
+
if block
|
19
|
+
expression = block.call
|
20
|
+
result = eval(expression, block.binding)
|
21
|
+
stream.printf("%-16s => %s\n", expression, result.inspect)
|
22
|
+
result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
def separator() end
|
27
|
+
def bench_output(desc = nil, stream = STDOUT, &block) end
|
28
|
+
end
|
29
|
+
end
|
data/test/test_basic.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestBasic < Test::Unit::TestCase
|
4
|
+
def test_define
|
5
|
+
(1..20).each { |threads|
|
6
|
+
CompTree.build { |driver|
|
7
|
+
driver.define(:area, :width, :height, :offset) { |width, height, offset|
|
8
|
+
width*height - offset
|
9
|
+
}
|
10
|
+
|
11
|
+
driver.define(:width, :border) { |border|
|
12
|
+
2 + border
|
13
|
+
}
|
14
|
+
|
15
|
+
driver.define(:height, :border) { |border|
|
16
|
+
3 + border
|
17
|
+
}
|
18
|
+
|
19
|
+
driver.define(:border) {
|
20
|
+
5
|
21
|
+
}
|
22
|
+
|
23
|
+
driver.define(:offset) {
|
24
|
+
7
|
25
|
+
}
|
26
|
+
|
27
|
+
assert_equal((2 + 5)*(3 + 5) - 7, driver.compute(:area, threads))
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_already_computed
|
33
|
+
[nil, false, true, 33].each { |result|
|
34
|
+
CompTree.build { |driver|
|
35
|
+
driver.define(:a) { result }
|
36
|
+
(1..3).each { |n|
|
37
|
+
assert_equal(result, driver.compute(:a, n))
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_threads_opt
|
44
|
+
(1..20).each { |threads|
|
45
|
+
CompTree.build do |driver|
|
46
|
+
driver.define(:a) { 33 }
|
47
|
+
assert_equal(33, driver.compute(:a, :threads => threads))
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_malformed
|
53
|
+
CompTree.build { |driver|
|
54
|
+
assert_raise(CompTree::ArgumentError) {
|
55
|
+
driver.define {
|
56
|
+
}
|
57
|
+
}
|
58
|
+
assert_raise(CompTree::RedefinitionError) {
|
59
|
+
driver.define(:a) {
|
60
|
+
}
|
61
|
+
driver.define(:a) {
|
62
|
+
}
|
63
|
+
}
|
64
|
+
assert_raise(CompTree::ArgumentError) {
|
65
|
+
driver.define(:b) {
|
66
|
+
}
|
67
|
+
driver.compute(:b, 0)
|
68
|
+
}
|
69
|
+
assert_raise(CompTree::ArgumentError) {
|
70
|
+
driver.define(:c) {
|
71
|
+
}
|
72
|
+
driver.compute(:c, -1)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_exception_in_compute
|
78
|
+
test_error = Class.new(RuntimeError)
|
79
|
+
CompTree.build { |driver|
|
80
|
+
driver.define(:area, :width, :height, :offset) { |width, height, offset|
|
81
|
+
width*height - offset
|
82
|
+
}
|
83
|
+
|
84
|
+
driver.define(:width, :border) { |border|
|
85
|
+
2 + border
|
86
|
+
}
|
87
|
+
|
88
|
+
driver.define(:height, :border) { |border|
|
89
|
+
3 + border
|
90
|
+
}
|
91
|
+
|
92
|
+
driver.define(:border) {
|
93
|
+
raise test_error
|
94
|
+
}
|
95
|
+
|
96
|
+
driver.define(:offset) {
|
97
|
+
7
|
98
|
+
}
|
99
|
+
|
100
|
+
assert_raise(test_error) {
|
101
|
+
driver.compute(:area, 6)
|
102
|
+
}
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_node_subclass
|
107
|
+
data = Object.new
|
108
|
+
subclass = Class.new(CompTree::Node) {
|
109
|
+
define_method :stuff do
|
110
|
+
data
|
111
|
+
end
|
112
|
+
}
|
113
|
+
CompTree.build(:node_class => subclass) { |driver|
|
114
|
+
driver.define(:a) { }
|
115
|
+
assert_equal(data, driver.nodes[:a].stuff)
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_non_symbols
|
120
|
+
width_id = Object.new
|
121
|
+
height_id = 272727
|
122
|
+
(1..3).each { |threads|
|
123
|
+
CompTree.build { |driver|
|
124
|
+
driver.define("area", width_id, height_id, :offset) {
|
125
|
+
|width, height, offset|
|
126
|
+
width*height - offset
|
127
|
+
}
|
128
|
+
|
129
|
+
driver.define(width_id, :border) { |border|
|
130
|
+
2 + border
|
131
|
+
}
|
132
|
+
|
133
|
+
driver.define(height_id, :border) { |border|
|
134
|
+
3 + border
|
135
|
+
}
|
136
|
+
|
137
|
+
driver.define(:border) {
|
138
|
+
5
|
139
|
+
}
|
140
|
+
|
141
|
+
driver.define(:offset) {
|
142
|
+
7
|
143
|
+
}
|
144
|
+
|
145
|
+
assert_equal((2 + 5)*(3 + 5) - 7, driver.compute("area", threads))
|
146
|
+
}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_node_name_equality_comparison
|
151
|
+
CompTree.build { |driver|
|
152
|
+
driver.define("hello") { }
|
153
|
+
assert_raise(CompTree::RedefinitionError) {
|
154
|
+
driver.define("hello") { }
|
155
|
+
}
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_result_variety
|
160
|
+
[true, false, nil, Object.new, 33].each { |result|
|
161
|
+
(1..20).each { |threads|
|
162
|
+
CompTree.build { |driver|
|
163
|
+
driver.define(:area, :width, :height, :offset) {
|
164
|
+
|width, height, offset|
|
165
|
+
result
|
166
|
+
}
|
167
|
+
|
168
|
+
driver.define(:width, :border) { |border|
|
169
|
+
result
|
170
|
+
}
|
171
|
+
|
172
|
+
driver.define(:height, :border) { |border|
|
173
|
+
result
|
174
|
+
}
|
175
|
+
|
176
|
+
driver.define(:border) {
|
177
|
+
result
|
178
|
+
}
|
179
|
+
|
180
|
+
driver.define(:offset) {
|
181
|
+
result
|
182
|
+
}
|
183
|
+
|
184
|
+
assert_equal(result, driver.compute(:area, threads))
|
185
|
+
}
|
186
|
+
}
|
187
|
+
}
|
188
|
+
end
|
189
|
+
end
|
data/test/test_circular.rb
CHANGED
@@ -1,36 +1,39 @@
|
|
1
|
-
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
class TestCircular < Test::Unit::TestCase
|
4
|
+
def test_circular
|
5
|
+
CompTree.build { |driver|
|
6
|
+
driver.define(:area, :width, :height, :offset) { |width, height, offset|
|
7
|
+
width*height - offset
|
8
|
+
}
|
9
|
+
|
10
|
+
driver.define(:width, :border) { |border|
|
11
|
+
2 + border
|
12
|
+
}
|
13
|
+
|
14
|
+
driver.define(:height, :border) { |border|
|
15
|
+
3 + border
|
16
|
+
}
|
17
|
+
|
18
|
+
driver.define(:border) {
|
19
|
+
5
|
20
|
+
}
|
21
|
+
|
22
|
+
driver.define(:offset, :area) {
|
23
|
+
7
|
24
|
+
}
|
5
25
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
driver.define(:area, :width, :height, :offset) { |width, height, offset|
|
11
|
-
width*height - offset
|
12
|
-
}
|
13
|
-
|
14
|
-
driver.define(:width, :border) { |border|
|
15
|
-
2 + border
|
16
|
-
}
|
17
|
-
|
18
|
-
driver.define(:height, :border) { |border|
|
19
|
-
3 + border
|
20
|
-
}
|
21
|
-
|
22
|
-
driver.define(:border) {
|
23
|
-
5
|
24
|
-
}
|
25
|
-
|
26
|
-
driver.define(:offset, :area) {
|
27
|
-
7
|
28
|
-
}
|
26
|
+
assert_equal([:area, :offset, :area], driver.check_circular(:area))
|
27
|
+
assert_equal([:offset, :area, :offset], driver.check_circular(:offset))
|
28
|
+
}
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
}
|
34
|
-
|
31
|
+
def test_not_circular
|
32
|
+
CompTree.build { |driver|
|
33
|
+
driver.define(:a, :b) { true }
|
34
|
+
driver.define(:b) { true }
|
35
|
+
assert_nil(driver.check_circular(:a))
|
36
|
+
assert_nil(driver.check_circular(:b))
|
37
|
+
}
|
35
38
|
end
|
36
39
|
end
|
data/test/test_drain.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestDrain < Test::Unit::TestCase
|
4
|
+
include TestCommon
|
5
|
+
|
6
|
+
def drain
|
7
|
+
500000.times { }
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_drain(threads)
|
11
|
+
CompTree.build { |driver|
|
12
|
+
func = lambda { |*args|
|
13
|
+
drain
|
14
|
+
}
|
15
|
+
driver.define(:area, :width, :height, :offset, &func)
|
16
|
+
driver.define(:width, :border, &func)
|
17
|
+
driver.define(:height, :border, &func)
|
18
|
+
driver.define(:border, &func)
|
19
|
+
driver.define(:offset, &func)
|
20
|
+
bench_output "number of threads: #{threads}"
|
21
|
+
bench = Benchmark.measure { driver.compute(:area, threads) }
|
22
|
+
bench_output bench
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def each_drain
|
27
|
+
(1..10).each { |threads|
|
28
|
+
yield threads
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_drain
|
33
|
+
separator
|
34
|
+
each_drain { |threads|
|
35
|
+
run_drain(threads)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
data/test/test_exception.rb
CHANGED
@@ -1,97 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
$LOAD_PATH.unshift LIB_DIR
|
16
|
-
$LOAD_PATH.unshift QUIX_LIB_DIR
|
17
|
-
end
|
18
|
-
|
19
|
-
require 'comp_tree'
|
20
|
-
require 'quix/config'
|
21
|
-
|
22
|
-
module CompTree
|
23
|
-
class TestRaises < Test::Unit::TestCase
|
24
|
-
include WorkaroundConfig
|
25
|
-
|
26
|
-
def test_exception
|
27
|
-
if RUBY_PLATFORM =~ %r!java!
|
28
|
-
puts "skipping #{File.basename(__FILE__)}."
|
29
|
-
else
|
30
|
-
[true, false].each { |use_fork|
|
31
|
-
[true, false].each { |define_all|
|
32
|
-
assert(
|
33
|
-
!system(
|
34
|
-
::Quix::Config.ruby_executable,
|
35
|
-
"-e",
|
36
|
-
code(use_fork, define_all)))
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestException < Test::Unit::TestCase
|
4
|
+
def test_exception
|
5
|
+
test_error = Class.new StandardError
|
6
|
+
[true, false].each { |define_all|
|
7
|
+
error = (
|
8
|
+
begin
|
9
|
+
CompTree.build { |driver|
|
10
|
+
driver.define(:area, :width, :height, :offset) {
|
11
|
+
|width, height, offset|
|
12
|
+
width*height - offset
|
13
|
+
}
|
37
14
|
|
38
|
-
|
15
|
+
driver.define(:width, :border) { |border|
|
16
|
+
2 + border
|
17
|
+
}
|
39
18
|
|
19
|
+
driver.define(:height, :border) { |border|
|
20
|
+
3 + border
|
21
|
+
}
|
22
|
+
|
40
23
|
if define_all
|
41
|
-
|
42
|
-
|
43
|
-
|
24
|
+
driver.define(:border) {
|
25
|
+
raise test_error
|
26
|
+
}
|
44
27
|
end
|
45
28
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
def code(use_fork, define_all)
|
53
|
-
%Q(
|
54
|
-
$LOAD_PATH.unshift '#{LIB_DIR}'
|
55
|
-
require 'comp_tree'
|
56
|
-
require 'open3'
|
57
|
-
|
58
|
-
class CompTreeTestError < Exception ; end
|
59
|
-
|
60
|
-
CompTree::Driver.new { |driver|
|
61
|
-
driver.define(:area, :width, :height, :offset) {
|
62
|
-
|width, height, offset|
|
63
|
-
width*height - offset
|
64
|
-
}
|
65
|
-
|
66
|
-
driver.define(:width, :border) { |border|
|
67
|
-
2 + border
|
29
|
+
driver.define(:offset) {
|
30
|
+
7
|
31
|
+
}
|
32
|
+
|
33
|
+
driver.compute(:area, 99)
|
68
34
|
}
|
35
|
+
nil
|
36
|
+
rescue => e
|
37
|
+
e
|
38
|
+
end
|
39
|
+
)
|
69
40
|
|
70
|
-
driver.define(:height, :border) { |border|
|
71
|
-
3 + border
|
72
|
-
}
|
73
|
-
) +
|
74
41
|
if define_all
|
75
|
-
|
76
|
-
driver.define(:border) {
|
77
|
-
raise CompTreeTestError
|
78
|
-
}
|
79
|
-
)
|
42
|
+
assert_block { error.is_a? test_error }
|
80
43
|
else
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
driver.define(:offset) {
|
85
|
-
7
|
86
|
-
}
|
87
|
-
|
88
|
-
File.open('#{OUTPUT_FILE}', "w") { |out|
|
89
|
-
$stderr = out
|
90
|
-
driver.compute(
|
91
|
-
:area, :threads => 99, :fork => #{use_fork.inspect})
|
92
|
-
}
|
93
|
-
}
|
94
|
-
)
|
95
|
-
end
|
44
|
+
assert_block { error.is_a? CompTree::NoFunctionError }
|
45
|
+
end
|
46
|
+
}
|
96
47
|
end
|
97
48
|
end
|
data/test/test_flood.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestFlood < Test::Unit::TestCase
|
4
|
+
def test_thread_flood
|
5
|
+
(1..200).each { |num_threads|
|
6
|
+
CompTree.build { |driver|
|
7
|
+
noop = lambda { |*args| true }
|
8
|
+
driver.define(:a, :b, &noop)
|
9
|
+
driver.define(:b, &noop)
|
10
|
+
driver.compute(:a, num_threads)
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
data/test/test_grind.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestGrind < Test::Unit::TestCase
|
4
|
+
include TestCommon
|
5
|
+
|
6
|
+
GENERATOR_DATA = {
|
7
|
+
:level_range => 1..4,
|
8
|
+
:children_range => 1..6,
|
9
|
+
:thread_range => 1..6,
|
10
|
+
:drain_iterations => 0,
|
11
|
+
}
|
12
|
+
|
13
|
+
ROOT = 'a'
|
14
|
+
|
15
|
+
def test_grind
|
16
|
+
run_generated_tree(GENERATOR_DATA)
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate_comp_tree(num_levels, num_children, drain_iterations)
|
20
|
+
CompTree.build { |driver|
|
21
|
+
name_gen = ROOT.dup
|
22
|
+
pick_names = lambda { |*args|
|
23
|
+
(0..rand(num_children)).map {
|
24
|
+
name_gen.succ!
|
25
|
+
name_gen.dup
|
26
|
+
}
|
27
|
+
}
|
28
|
+
drain = lambda { |*args|
|
29
|
+
drain_iterations.times {
|
30
|
+
}
|
31
|
+
}
|
32
|
+
build_tree = lambda { |parent, children, level|
|
33
|
+
#trace "building #{parent} --> #{children.join(' ')}"
|
34
|
+
|
35
|
+
driver.define(parent, *children, &drain)
|
36
|
+
|
37
|
+
if level < num_levels
|
38
|
+
children.each { |child|
|
39
|
+
build_tree.call(child, pick_names.call, level + 1)
|
40
|
+
}
|
41
|
+
else
|
42
|
+
children.each { |child|
|
43
|
+
driver.define(child, &drain)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
}
|
47
|
+
build_tree.call(ROOT, pick_names.call, drain_iterations)
|
48
|
+
driver
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def run_generated_tree(args)
|
53
|
+
args[:level_range].each { |num_levels|
|
54
|
+
args[:children_range].each { |num_children|
|
55
|
+
separator
|
56
|
+
bench_output {%{num_levels}}
|
57
|
+
bench_output {%{num_children}}
|
58
|
+
driver = generate_comp_tree(
|
59
|
+
num_levels,
|
60
|
+
num_children,
|
61
|
+
args[:drain_iterations])
|
62
|
+
args[:thread_range].each { |threads|
|
63
|
+
bench_output {%{threads}}
|
64
|
+
2.times {
|
65
|
+
driver.reset(ROOT)
|
66
|
+
result = nil
|
67
|
+
bench = Benchmark.measure {
|
68
|
+
result = driver.compute(ROOT, threads)
|
69
|
+
}
|
70
|
+
bench_output bench
|
71
|
+
assert_equal(result, args[:drain_iterations])
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/common"
|
2
|
+
|
3
|
+
class TestSequential < Test::Unit::TestCase
|
4
|
+
def test_sequential
|
5
|
+
(1..50).each { |num_threads|
|
6
|
+
[1, 2, 3, 20, 50].each { |num_nodes|
|
7
|
+
CompTree.build { |driver|
|
8
|
+
driver.define(:root) { true }
|
9
|
+
(1..num_nodes).each { |n|
|
10
|
+
if n == 0
|
11
|
+
driver.define("a#{n}".to_s, :root) { true }
|
12
|
+
else
|
13
|
+
driver.define("a#{n}".to_s, "a#{n-1}".to_s) { true }
|
14
|
+
end
|
15
|
+
}
|
16
|
+
driver.compute(:root, num_threads)
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|