tiamat 0.1.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/CHANGES.rdoc +7 -0
- data/MANIFEST +42 -0
- data/README.rdoc +194 -0
- data/Rakefile +19 -0
- data/bin/tiamat-server +31 -0
- data/devel/jumpstart.rb +987 -0
- data/install.rb +2 -0
- data/lib/tiamat.rb +43 -0
- data/lib/tiamat/autoconfig.rb +8 -0
- data/lib/tiamat/child_server.rb +21 -0
- data/lib/tiamat/config/ruby_parser.rb +6 -0
- data/lib/tiamat/connector.rb +23 -0
- data/lib/tiamat/error.rb +24 -0
- data/lib/tiamat/farm.rb +32 -0
- data/lib/tiamat/local_child_farm.rb +23 -0
- data/lib/tiamat/local_child_server.rb +25 -0
- data/lib/tiamat/local_child_worker.rb +11 -0
- data/lib/tiamat/remote_farm.rb +11 -0
- data/lib/tiamat/remote_worker.rb +10 -0
- data/lib/tiamat/server.rb +42 -0
- data/lib/tiamat/tiamat.rb +49 -0
- data/lib/tiamat/tiamat_server.rb +48 -0
- data/lib/tiamat/util.rb +37 -0
- data/lib/tiamat/version.rb +4 -0
- data/lib/tiamat/worker.rb +61 -0
- data/spec/connector_spec.rb +11 -0
- data/spec/drb_connection_spec.rb +18 -0
- data/spec/local_child_farm_spec.rb +29 -0
- data/spec/local_child_server_path_spec.rb +37 -0
- data/spec/local_child_server_spec.rb +24 -0
- data/spec/local_child_worker_spec.rb +140 -0
- data/spec/pure_spec.rb +59 -0
- data/spec/readme_spec.rb +29 -0
- data/spec/remote_farm_spec.rb +36 -0
- data/spec/remote_worker_spec.rb +59 -0
- data/spec/server_spec.rb +48 -0
- data/spec/tiamat_open_local_spec.rb +77 -0
- data/spec/tiamat_open_remote_spec.rb +67 -0
- data/spec/tiamat_server_spec.rb +51 -0
- data/spec/tiamat_spec_base.rb +36 -0
- data/spec/util_spec.rb +29 -0
- data/spec/worker_spec.rb +19 -0
- metadata +209 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
module Tiamat
|
3
|
+
class Worker
|
4
|
+
def define_function_begin(pure_module, num_parallel)
|
5
|
+
end
|
6
|
+
|
7
|
+
def define_function(spec)
|
8
|
+
lambda { |*args|
|
9
|
+
self.class.farm.lend_server { |server|
|
10
|
+
server.evaluate_function(spec, *args)
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def define_function_end
|
16
|
+
end
|
17
|
+
|
18
|
+
def num_parallel
|
19
|
+
self.class.num_parallel
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
attr_reader :farm
|
24
|
+
|
25
|
+
def open(farm)
|
26
|
+
unless closed?
|
27
|
+
raise AlreadyOpenError.new(self)
|
28
|
+
end
|
29
|
+
@farm = farm
|
30
|
+
if block_given?
|
31
|
+
previous_worker = Pure.worker
|
32
|
+
Pure.worker = self
|
33
|
+
begin
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
Pure.worker = previous_worker
|
37
|
+
close
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def close
|
43
|
+
unless closed?
|
44
|
+
@farm.close
|
45
|
+
@farm = nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def closed?
|
50
|
+
not defined?(@farm) or @farm.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
def num_parallel
|
54
|
+
@farm.num_servers
|
55
|
+
end
|
56
|
+
|
57
|
+
def num_parallel=(value)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe Tiamat::Connector do
|
4
|
+
it "should raise for nonexistent server" do
|
5
|
+
lambda {
|
6
|
+
Tiamat::Connector.connect(0.1, 0.5) {
|
7
|
+
DRbObject.new_with_uri("druby://localhost:9999").foo
|
8
|
+
}
|
9
|
+
}.should raise_error(DRb::DRbConnError)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe "drb connection" do
|
4
|
+
before :all do
|
5
|
+
@uri = "druby://localhost:22334"
|
6
|
+
@server = Tiamat::LocalChildServer.new(@uri, *Tiamat.compiler.reverse)
|
7
|
+
end
|
8
|
+
|
9
|
+
after :all do
|
10
|
+
@server.close
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be creatable" do
|
14
|
+
@server.instance_eval do
|
15
|
+
@drb_object.ping
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe Tiamat::LocalChildFarm do
|
4
|
+
before :all do
|
5
|
+
@farm = Tiamat::LocalChildFarm.new(4, *Tiamat.compiler.reverse)
|
6
|
+
end
|
7
|
+
|
8
|
+
after :all do
|
9
|
+
@farm.close
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should provide local servers" do
|
13
|
+
mod = pure(Pure::Parser::RubyParser) do
|
14
|
+
def f
|
15
|
+
33 + 44
|
16
|
+
end
|
17
|
+
end
|
18
|
+
spec = Pure::ExtractedFunctions[Pure::Parser::RubyParser][mod][:f]
|
19
|
+
|
20
|
+
20.times {
|
21
|
+
@farm.lend_server { |server_a|
|
22
|
+
@farm.lend_server { |server_b|
|
23
|
+
server_a.evaluate_function(spec).should eql(77)
|
24
|
+
server_b.evaluate_function(spec).should eql(77)
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe "Tiamat::LocalChildServer launch" do
|
4
|
+
before :all do
|
5
|
+
require 'fileutils'
|
6
|
+
@dummy_server = File.expand_path(
|
7
|
+
File.dirname(__FILE__) +
|
8
|
+
"/data/" +
|
9
|
+
Tiamat::LocalChildServer.server_basename
|
10
|
+
)
|
11
|
+
FileUtils.mkdir_p(File.dirname(@dummy_server))
|
12
|
+
FileUtils.touch(@dummy_server)
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
FileUtils.rm_r(File.dirname(@dummy_server))
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should prefer #{Tiamat::LocalChildServer.server_basename} in path" do
|
20
|
+
new_path = (
|
21
|
+
ENV["PATH"].
|
22
|
+
split(File::PATH_SEPARATOR).
|
23
|
+
unshift(File.dirname(@dummy_server))
|
24
|
+
).join(File::PATH_SEPARATOR)
|
25
|
+
|
26
|
+
fallback = File.expand_path(
|
27
|
+
File.dirname(__FILE__) +
|
28
|
+
"/../bin/" +
|
29
|
+
Tiamat::LocalChildServer.server_basename
|
30
|
+
)
|
31
|
+
Tiamat::LocalChildServer.server_path.should eql(fallback)
|
32
|
+
TiamatSpecBase.with_env("PATH" => new_path) {
|
33
|
+
Tiamat::LocalChildServer.server_path.should eql(@dummy_server)
|
34
|
+
}
|
35
|
+
Tiamat::LocalChildServer.server_path.should eql(fallback)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe Tiamat::LocalChildServer do
|
4
|
+
before :all do
|
5
|
+
@server = Tiamat::LocalChildServer.new(
|
6
|
+
"druby://localhost:27272", *Tiamat.compiler.reverse
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
after :all do
|
11
|
+
@server.close
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should evaluate a pure function spec" do
|
15
|
+
mod = pure(Pure::Parser::RubyParser) do
|
16
|
+
def f
|
17
|
+
33 + 44
|
18
|
+
end
|
19
|
+
end
|
20
|
+
spec = Pure::ExtractedFunctions[Pure::Parser::RubyParser][mod][:f]
|
21
|
+
|
22
|
+
@server.evaluate_function(spec).should == 77
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
describe Tiamat::LocalChildWorker do
|
6
|
+
before :all do
|
7
|
+
Tiamat::LocalChildWorker.open(2, *Tiamat.compiler.reverse)
|
8
|
+
end
|
9
|
+
|
10
|
+
after :all do
|
11
|
+
Tiamat::LocalChildWorker.close
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should evaluate a pure function with no args" do
|
15
|
+
result = pure do
|
16
|
+
def f
|
17
|
+
11 + 22
|
18
|
+
end
|
19
|
+
end.compute(Tiamat::LocalChildWorker)
|
20
|
+
|
21
|
+
result.f.should == 33
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should evaluate a pure function with args" do
|
25
|
+
mod = pure do
|
26
|
+
def f(x, y)
|
27
|
+
x + y
|
28
|
+
end
|
29
|
+
def x
|
30
|
+
33
|
31
|
+
end
|
32
|
+
def y
|
33
|
+
44
|
34
|
+
end
|
35
|
+
end.compute(Tiamat::LocalChildWorker).f.should == 77
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should handle `fun' definitions with no args" do
|
39
|
+
pure do
|
40
|
+
fun :f do
|
41
|
+
11 + 22
|
42
|
+
end
|
43
|
+
end.compute(Tiamat::LocalChildWorker).f.should == 33
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should handle `fun' definitions with args" do
|
47
|
+
pure do
|
48
|
+
fun :f => [:x, :y] do |u, v|
|
49
|
+
u*v
|
50
|
+
end
|
51
|
+
|
52
|
+
fun :x do
|
53
|
+
4
|
54
|
+
end
|
55
|
+
|
56
|
+
def y
|
57
|
+
5
|
58
|
+
end
|
59
|
+
end.compute(Tiamat::LocalChildWorker).f.should == 20
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be around 2x faster with 2 servers" do
|
63
|
+
mod = pure do
|
64
|
+
def total(left, right)
|
65
|
+
left + right
|
66
|
+
end
|
67
|
+
|
68
|
+
def left
|
69
|
+
(1..250_000).inject(0) { |acc, n| acc + n }
|
70
|
+
end
|
71
|
+
|
72
|
+
def right
|
73
|
+
(1..250_000).inject(0) { |acc, n| acc + n }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
default_result = nil
|
78
|
+
default_time = mod.compute(2) { |result|
|
79
|
+
Benchmark.measure {
|
80
|
+
default_result = result.total
|
81
|
+
}.real
|
82
|
+
}
|
83
|
+
|
84
|
+
tiamat_result = nil
|
85
|
+
tiamat_time = mod.compute(Tiamat::LocalChildWorker) { |result|
|
86
|
+
Benchmark.measure {
|
87
|
+
tiamat_result = result.total
|
88
|
+
}.real
|
89
|
+
}
|
90
|
+
|
91
|
+
expected = 250_000*(250_000 + 1)
|
92
|
+
default_result.should eql(expected)
|
93
|
+
tiamat_result.should eql(expected)
|
94
|
+
|
95
|
+
# jruby is slow
|
96
|
+
epsilon = 0.65 + (RUBY_PLATFORM == "java" ? 1.0 : 0)
|
97
|
+
if ARGV.include? "--bench"
|
98
|
+
puts
|
99
|
+
puts "-----------"
|
100
|
+
puts "tiamat #{tiamat_time}"
|
101
|
+
puts "default #{default_time}"
|
102
|
+
puts
|
103
|
+
puts "ratio #{tiamat_time/default_time}"
|
104
|
+
puts "-----------"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should propagate exceptions from root function" do
|
109
|
+
mod = pure do
|
110
|
+
def f
|
111
|
+
raise "zz"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
result = mod.compute(4)
|
115
|
+
lambda {
|
116
|
+
result.f
|
117
|
+
}.should raise_error(RuntimeError, "zz")
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should propagate exceptions from child functions" do
|
121
|
+
mod = pure do
|
122
|
+
def f(x)
|
123
|
+
33
|
124
|
+
end
|
125
|
+
|
126
|
+
def x(y)
|
127
|
+
44
|
128
|
+
end
|
129
|
+
|
130
|
+
def y
|
131
|
+
raise "foo"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
result = mod.compute(4)
|
135
|
+
lambda {
|
136
|
+
result.f
|
137
|
+
}.should raise_error(RuntimeError, "foo")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
data/spec/pure_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe Pure do
|
4
|
+
before :all do
|
5
|
+
border = pure do
|
6
|
+
def border
|
7
|
+
2
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
@geometry = pure do
|
12
|
+
include border
|
13
|
+
|
14
|
+
def area(width, height)
|
15
|
+
width*height
|
16
|
+
end
|
17
|
+
|
18
|
+
def width(border)
|
19
|
+
7 + border
|
20
|
+
end
|
21
|
+
|
22
|
+
def height(border)
|
23
|
+
5 + border
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should use the custom worker assigned to Pure.worker" do
|
29
|
+
expected = {
|
30
|
+
:area => [:width, :height],
|
31
|
+
:width => [:border],
|
32
|
+
:height => [:border],
|
33
|
+
:border => [],
|
34
|
+
}
|
35
|
+
|
36
|
+
actual = Hash.new
|
37
|
+
|
38
|
+
worker = Class.new do
|
39
|
+
def num_parallel
|
40
|
+
2
|
41
|
+
end
|
42
|
+
|
43
|
+
def define_function_begin(*args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def define_function_end(*args)
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method :define_function do |spec|
|
50
|
+
lambda { |*a|
|
51
|
+
actual[spec[:name]] = spec[:args]
|
52
|
+
}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@geometry.compute(worker).area
|
57
|
+
actual.should == expected
|
58
|
+
end
|
59
|
+
end
|
data/spec/readme_spec.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
require "jumpstart"
|
4
|
+
|
5
|
+
readme = "README.rdoc"
|
6
|
+
|
7
|
+
Jumpstart.doc_to_spec(readme, "Synopsis") {
|
8
|
+
|expected_str, actual_str, index|
|
9
|
+
|
10
|
+
expected, actual = [expected_str, actual_str].map { |expr|
|
11
|
+
expr.should match(%r!\A\d+\.\d+\n\d+\.\d+\Z!)
|
12
|
+
expr.split.map { |s| s.to_f }
|
13
|
+
}.map { |pair|
|
14
|
+
{
|
15
|
+
:one_cpu => pair[0],
|
16
|
+
:two_cpu => pair[1],
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
[expected, actual].each { |result|
|
21
|
+
epsilon = 0.15 + TiamatSpecBase.slow_platform_epsilon
|
22
|
+
(result[:two_cpu]/result[:one_cpu]).should be_close(0.5, epsilon)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
Jumpstart.doc_to_spec(readme, "Adding +require+ Paths to Local Servers")
|
27
|
+
|
28
|
+
Jumpstart.doc_to_spec(readme, "About DRbConnError")
|
29
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/tiamat_spec_base'
|
2
|
+
|
3
|
+
describe Tiamat::RemoteFarm do
|
4
|
+
before :all do
|
5
|
+
uris = (47055..47060).map { |n|
|
6
|
+
"druby://localhost:#{n}"
|
7
|
+
}
|
8
|
+
@servers = uris.map { |uri|
|
9
|
+
Tiamat::LocalChildServer.new(uri, *Tiamat.compiler.reverse)
|
10
|
+
}
|
11
|
+
@farm = Tiamat::RemoteFarm.new(*uris)
|
12
|
+
Tiamat::Worker.open(@farm)
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
Tiamat::Worker.close
|
17
|
+
@farm.close
|
18
|
+
@servers.each { |s| s.close }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be useable by a worker" do
|
22
|
+
pure(Pure::Parser::RubyParser) do
|
23
|
+
def f(x, y)
|
24
|
+
x + y
|
25
|
+
end
|
26
|
+
|
27
|
+
def x
|
28
|
+
33
|
29
|
+
end
|
30
|
+
|
31
|
+
def y
|
32
|
+
44
|
33
|
+
end
|
34
|
+
end.compute(Tiamat::Worker).f.should == 77
|
35
|
+
end
|
36
|
+
end
|