brabuhr@gmail.com wrote:
I took a quick shot w/ duby-inline.
...
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
user system total real
18.210000 0.040000 18.250000 ( 21.596111)
...
jruby 1.5.0 (ruby 1.8.7 patchlevel 249) (2010-05-12 6769999) (OpenJDK
Server VM 1.6.0_18) [i386-java]
0.208000 0.000000 0.208000 ( 0.208000)
That is a very impressive speed-up!
I see a more modest improvement going from the same original code (on different hardware of course) to a version written in redshift. Of course, redshift is using a more accurate integration algorithm (with 4 substeps instead of 1). Plus there are costs for the availability of other features that are not being used in this example (e.g., a layer of function pointers so that variables can switch to different equations when a discrete state change occurs).
$ ruby bench-rb.rb
user system total real
evolve 6s 0.710000 0.160000 0.870000 ( 0.881276)
evolve 600s 15.320000 1.010000 16.330000 ( 16.366811)
$ ruby bench-rs.rb
user system total real
evolve 6s 0.020000 0.000000 0.020000 ( 0.025213)
evolve 600s 1.170000 0.000000 1.170000 ( 1.178752)
$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
Here are the sources:
$ cat bench-rb.rb
G = 9.8
def velocity(c, m, t, dt, vi)
t += dt
steps = t/dt
i = 0
while i < steps
v = vi
vi = v + ( G - c/m*v) * dt
i += 1
end
vi
end
require 'benchmark'
Benchmark.bm(12) do |b|
b.report("evolve 6s") do
100000.times do
velocity(0.5, 21.6, 6.0, 10.0, 0.0)
# Note: I changed the t and dt to floats for a more direct
# comparison with redshift, which uses floats for time values
end
end
b.report("evolve 600s") do
100000.times do
velocity(0.5, 21.6, 600.0, 10.0, 0.0)
end
end
end
$ cat bench-rs.rb
require 'redshift'
class Thing < RedShift::Component
continuous :v
constant :m, :c, :G
flow do
differential " v' = G - c/m * v "
end
end
def make_world(n)
RedShift::World.new do |world|
world.time_step = 10.0
n.times do
world.create Thing do |thing|
thing.m = 21.6
thing.c = 0.5
thing.v = 0
thing.G = 9.8
end
end
end
end
require 'benchmark'
Benchmark.bm(12) do |b|
n = 1000
reps = 100
# Note: instead of 100000 sequential runs, this benchmark is doing
# 100 sequential runs of 1000 parallel instances of the same
# integration problem, which is more typical of the conditions
# redshift is optimized for
world = make_world(n)
b.report("evolve 6s") do
reps.times do
world.evolve 6.0
end
end
world = make_world(n)
b.report("evolve 600s") do
reps.times do
world.evolve 600.0
end
end
end