[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: Intensive computing: Ruby? Ruby/C? Pure C++?

benjohn

1/17/2007 10:48:00 AM

> Thanks a lot for your time and in advance for any responses. :)

I'd go with prototype in Ruby, probably.

You could jump in to c++, and I think you may find useful Boost
libraries for the work you're going (there is a graph librarby in there,
I'm sure), but I honestly think you'll suffer if you're not a c++ Guru,
particularly if you're using template based libraries (others will
probably differ, but my feeling is using c++ well is very hard, and I'm
paid to do it ;-).

After prototyping, a fourth way that I would strongly suggest in this
case, is to considder a functional language if you need speed. That may
sound crazy, but ocaml [1] (specifically) performs comparably (half as
fast?) as hand tuned c on benchmarks [2] (lies, damned lies and
statistics?). It's almost certainly very well suited to the kind of work
you're talking about (symbolic manipulation), and your brain may enjoy
molding to the mind set if it's already got Ruby nestled in there.

If the prototype is going to be a large lump of work, you might even
want to considder starting out with the functional language
(particularly if you can find example code for a similar looking
problem).

:) All the best!

Cheers,
Benjohn

[1] http://caml.inria.fr/ocaml/ind...
[2] http://www.cs.ubc.ca/~murphyk/Software/Ocaml/why_...


11 Answers

benjohn

1/17/2007 10:57:00 AM

0

P.S. You may also find that there are languages or tools out there that
are very well focused to your domain, in which case I'd very strongly
advise you to make use of them if at all possible. Is your PhD about
writing code to solve this problem; or about exploring the complexity
and implications of algorithms; or even about actually making use of the
algorithm? It all depends on what your goal is, really.


Shot (Piotr Szotkowski)

1/17/2007 6:05:00 PM

0

Thanks a lot for taking the time to reply, Benjohn!

benjohn@fysh.org:

> I'd go with prototype in Ruby, probably.

And then...? I hoped a bit for the dream solution of "actually, dear
professors, it works - if slow - for the scope of this thesis, and
further speed improvements can be achieved by replacing more parts
with C/C++ code". ;)

> You could jump in to c++, and I think you may find useful Boost
> libraries for the work you're going (there is a graph librarby in
> there, I'm sure)

Yeah, I heard good things about Boost, and also that wrapping one's mind
around C++ templating is a requirement these days. Of which, the latter
scares me (and I seem to know my limits quite well)...

> but I honestly think you'll suffer if you're not a c++ Guru

My thoughts exactly. The catch is my supervisor codes in C++ all his
life, while not having any idea about script languages, so he doesn't
really seem to easily buy mine 'I'll code both faster and be way more
happy with Ruby/OCaml, and the finished libraries will be more-or-less
universal anyway.'

> After prototyping, a fourth way that I would strongly suggest in
> this case, is to considder a functional language if you need speed.

The catch with going OCaml (where did today go? all these
easily-googlable tutorials and opinions were so nice to read...)
is that I'll have to learn yet another language (and, more importantly,
design paradigm).

What I forgot to mention, my supervisor suggests I could re-use a lot of
his C++ base classes; I wonder how well (objective) C++ integrates with
Ruby/OCaml (if at all).

> It's almost certainly very well suited to the kind of work you're
> talking about (symbolic manipulation), and your brain may enjoy
> molding to the mind set if it's already got Ruby nestled in there.

I'll give it an afternoon or two, thanks a lot for the suggestion! The
catch is that my supervisor's brain would also have to mold accordingly,
and that might be the tricky part for a C++-only person ('functional
programming? in 2007?! can't you just code in C++ like all the normal
people?').

> P.S. You may also find that there are languages or tools out there
> that are very well focused to your domain, in which case I'd very
> strongly advise you to make use of them if at all possible.

Definitely. Part of the problem is that I'm not yet
sure what domains will the final alogrithm cover... :)

> Is your PhD about writing code to solve this problem; or about
> exploring the complexity and implications of algorithms; or even
> about actually making use of the algorithm?

It's about (a) coming up with an algorithm (so far it seems it'll
be mostly based on blanket algebra, so set-based operations) and
(b) implementing the algorithm in any way I see fit (although one
that's graspable and reusable by others is expected, so I'm a bit
affraid with going OCaml here; still, any non-C++ solution will be
a slap to the face, I guess).

-- Shot
--
> Templates and generic programming: they are as close to duck typing
> as you can get - implement the required signature and you're off.
> The Vigra toolkit I've been using is a great example of this.
I first parsed this as 'Viagra toolkit', and thought, won't that just
make things harder? -- Ara.T.Howard and James Britt, ruby-talk

William James

1/17/2007 7:05:00 PM

0

Shot (Piotr Szotkowski) wrote:
> Thanks a lot for taking the time to reply, Benjohn!
>
> benjohn@fysh.org:
>
> > I'd go with prototype in Ruby, probably.
>
> And then...? I hoped a bit for the dream solution of "actually, dear
> professors, it works - if slow - for the scope of this thesis, and
> further speed improvements can be achieved by replacing more parts
> with C/C++ code". ;)
>
> > You could jump in to c++, and I think you may find useful Boost
> > libraries for the work you're going (there is a graph librarby in
> > there, I'm sure)
>
> Yeah, I heard good things about Boost, and also that wrapping one's mind
> around C++ templating is a requirement these days. Of which, the latter
> scares me (and I seem to know my limits quite well)...
>
> > but I honestly think you'll suffer if you're not a c++ Guru
>
> My thoughts exactly. The catch is my supervisor codes in C++ all his
> life, while not having any idea about script languages, so he doesn't
> really seem to easily buy mine 'I'll code both faster and be way more
> happy with Ruby/OCaml, and the finished libraries will be more-or-less
> universal anyway.'
>
> > After prototyping, a fourth way that I would strongly suggest in
> > this case, is to considder a functional language if you need speed.
>
> The catch with going OCaml (where did today go? all these
> easily-googlable tutorials and opinions were so nice to read...)
> is that I'll have to learn yet another language (and, more importantly,
> design paradigm).

LuaJIT probably won't be as fast as OCaml, but I think Lua
is easier for a Rubyist to learn.

William James

1/18/2007 6:09:00 AM

0

William James wrote:
> Shot (Piotr Szotkowski) wrote:
> > Thanks a lot for taking the time to reply, Benjohn!
> >
> > benjohn@fysh.org:
> >
> > > I'd go with prototype in Ruby, probably.
> >
> > And then...? I hoped a bit for the dream solution of "actually, dear
> > professors, it works - if slow - for the scope of this thesis, and
> > further speed improvements can be achieved by replacing more parts
> > with C/C++ code". ;)
> >
> > > You could jump in to c++, and I think you may find useful Boost
> > > libraries for the work you're going (there is a graph librarby in
> > > there, I'm sure)
> >
> > Yeah, I heard good things about Boost, and also that wrapping one's mind
> > around C++ templating is a requirement these days. Of which, the latter
> > scares me (and I seem to know my limits quite well)...
> >
> > > but I honestly think you'll suffer if you're not a c++ Guru
> >
> > My thoughts exactly. The catch is my supervisor codes in C++ all his
> > life, while not having any idea about script languages, so he doesn't
> > really seem to easily buy mine 'I'll code both faster and be way more
> > happy with Ruby/OCaml, and the finished libraries will be more-or-less
> > universal anyway.'
> >
> > > After prototyping, a fourth way that I would strongly suggest in
> > > this case, is to considder a functional language if you need speed.
> >
> > The catch with going OCaml (where did today go? all these
> > easily-googlable tutorials and opinions were so nice to read...)
> > is that I'll have to learn yet another language (and, more importantly,
> > design paradigm).
>
> LuaJIT probably won't be as fast as OCaml, but I think Lua
> is easier for a Rubyist to learn.

Comparing Ruby to Lua and LuaJIT for intensively computing primes:

Ruby 245.763 seconds
Lua 10.685 seconds
LuaJIT 1.311 seconds

# the Ruby program
def prime(n)
if n > 2 and n % 2 == 0
return false
end
3.step( Math.sqrt(n).floor, 2){|i|
if n % i == 0
return false
end
}
true
end

puts prime(2)
puts prime(4)
puts prime(7)
puts prime(25)
puts '----- the rest are primes'
time = Time.now
puts prime(1073676287)
puts prime(68718952447)
puts prime(87178291199)
puts prime(274877906899)
puts prime(549755813881)
puts prime(1099511627689)
puts prime(2199023255531)
puts prime(4398046511093)
puts prime(8796093022151)
puts prime(17592186044399)
puts prime(953467954114363)
puts Time.now - time


-- the Lua program
function prime(n)
if n > 2 and n % 2 == 0 then
return false
end
for i = 3, math.floor(math.sqrt(n)), 2 do
if n % i == 0 then
return false
end
end
return true
end

print(prime(2))
print(prime(4))
print(prime(7))
print(prime(25))
print('----- the rest are primes')
time = os.clock()
print(prime(1073676287))
print(prime(68718952447))
print(prime(87178291199))
print(prime(274877906899))
print(prime(549755813881))
print(prime(1099511627689))
print(prime(2199023255531))
print(prime(4398046511093))
print(prime(8796093022151))
print(prime(17592186044399))
print(prime(953467954114363))
print(os.clock() - time)

umptious

1/18/2007 12:29:00 PM

0

It sounds like you need to know C++, if only for political reasons.
This being so, buy a reasonable into book now, and, most importantly,
Scott Meyers "Effective C++". You'll be doomed without it!

William James

1/18/2007 5:40:00 PM

0

William James wrote:

>
> print(prime(2))
> print(prime(4))
> print(prime(7))
> print(prime(25))
> print('----- the rest are primes')
> time = os.clock()
> print(prime(1073676287))
> print(prime(68718952447))
> print(prime(87178291199))
> print(prime(274877906899))
> print(prime(549755813881))
> print(prime(1099511627689))
> print(prime(2199023255531))
> print(prime(4398046511093))
> print(prime(8796093022151))
> print(prime(17592186044399))
> print(prime(953467954114363))
> print(os.clock() - time)

A little less crude:

function report_primality( tbl )
for _, n in ipairs( tbl ) do
print( prime( n ) )
end
end

report_primality( { 2, 4, 7, 25 } )

print( '----- the rest are primes' )
time = os.clock()

report_primality( {
1073676287,
68718952447,
87178291199,
274877906899,
549755813881,
1099511627689,
2199023255531,
4398046511093,
8796093022151,
17592186044399,
953467954114363 } )

print(os.clock() - time)


Ruby 87.781 seconds
Lua 4.188 seconds
LuaJIT 0.718 seconds

Ryan Davis

1/18/2007 6:23:00 PM

0


On Jan 17, 2007, at 10:10 PM, William James wrote:

> Comparing Ruby to Lua and LuaJIT for intensively computing primes:
>
> Ruby 245.763 seconds
> Lua 10.685 seconds
> LuaJIT 1.311 seconds
>
> # the Ruby program
> def prime(n)
> if n > 2 and n % 2 == 0
> return false
> end
> 3.step( Math.sqrt(n).floor, 2){|i|
> if n % i == 0
> return false
> end
> }
> true
> end

I wrote mine a bit different:

def prime(n)
return false if n > 2 and n % 2 == 0
max = sqrt(n)
3.upto(max) do |i|
return false if i % 2 != 0 and n % i == 0
end
return true
end

optimize :prime

---

now, optimize converts it to C which doesn't have the benefits of big
numerics built in, but that doesn't sound like a problem for the OP.
Here are my times:

pure ruby: real 0m1.139s user 0m1.110s sys 0m0.009s
opt ruby: real 0m0.259s user 0m0.201s sys 0m0.056s

You can stay in ruby-land and eat your cake too.


William James

1/18/2007 7:08:00 PM

0

Ryan Davis wrote:
> On Jan 17, 2007, at 10:10 PM, William James wrote:
>
> > Comparing Ruby to Lua and LuaJIT for intensively computing primes:
> >
> > Ruby 245.763 seconds
> > Lua 10.685 seconds
> > LuaJIT 1.311 seconds
> >
> > # the Ruby program
> > def prime(n)
> > if n > 2 and n % 2 == 0
> > return false
> > end
> > 3.step( Math.sqrt(n).floor, 2){|i|
> > if n % i == 0
> > return false
> > end
> > }
> > true
> > end
>
> I wrote mine a bit different:
>
> def prime(n)
> return false if n > 2 and n % 2 == 0
> max = sqrt(n)
> 3.upto(max) do |i|
> return false if i % 2 != 0 and n % i == 0
> end
> return true
> end
>
> optimize :prime
>
> ---
>
> now, optimize converts it to C which doesn't have the benefits of big
> numerics built in, but that doesn't sound like a problem for the OP.
> Here are my times:
>
> pure ruby: real 0m1.139s user 0m1.110s sys 0m0.009s
> opt ruby: real 0m0.259s user 0m0.201s sys 0m0.056s

You're saying that pure Ruby took less than 2 seconds?
I don't see how that is possible. On the faster of the two
computers at my disposal your version ran in 207 seconds.

Ryan Davis

1/18/2007 9:35:00 PM

0


On Jan 18, 2007, at 11:10 AM, William James wrote:

> Ryan Davis wrote:
>> I wrote mine a bit different:
>>
>> def prime(n)
>> return false if n > 2 and n % 2 == 0
>> max = sqrt(n)
>> 3.upto(max) do |i|
>> return false if i % 2 != 0 and n % i == 0
>> end
>> return true
>> end
>>
>> optimize :prime
>

> You're saying that pure Ruby took less than 2 seconds?
> I don't see how that is possible. On the faster of the two
> computers at my disposal your version ran in 207 seconds.

Yes, on my computer it ran in 2 seconds, but I didn't have the same
driver as you did because I couldn't go into the bignum range. So I
did the biggest you had an extra 20 times instead.


William James

1/19/2007 2:44:00 AM

0

Ryan Davis wrote:
> On Jan 18, 2007, at 11:10 AM, William James wrote:
>
> > Ryan Davis wrote:
> >> I wrote mine a bit different:
> >>
> >> def prime(n)
> >> return false if n > 2 and n % 2 == 0
> >> max = sqrt(n)
> >> 3.upto(max) do |i|
> >> return false if i % 2 != 0 and n % i == 0
> >> end
> >> return true
> >> end
> >>
> >> optimize :prime
> >
>
> > You're saying that pure Ruby took less than 2 seconds?
> > I don't see how that is possible. On the faster of the two
> > computers at my disposal your version ran in 207 seconds.
>
> Yes, on my computer it ran in 2 seconds, but I didn't have the same
> driver as you did because I couldn't go into the bignum range. So I
> did the biggest you had an extra 20 times instead.

Your mentioning bignums made me wonder whether my previous
benchmark was fair to Ruby, since Lua was using 64-bit floats
instead of bignums. Here's a revised version that doesn't use
bignums.

# Ruby
def prime(n)
if n > 2 and n % 2 == 0
return false
end
3.step( Math.sqrt(n).floor, 2){|i|
if n % i == 0
return false
end
}
true
end

reps = 10
puts "Testing each number #{reps} times."
time = Time.now
count, prime_count = 0, 0

"
27 39, 79, 111, 115, 135, 187, 199, 219, 231, 235
28 57, 89, 95, 119, 125, 143, 165, 183, 213, 273
29 3, 33, 43, 63, 73, 75, 93, 99, 121, 133
30 35, 41, 83, 101, 105, 107, 135, 153, 161, 173
".scan( /[^\n]+/ ){|line|
exp = nil
line.scan( /\d+/ ){|digits|
if exp
number = 2**exp - digits.to_i
bool = false
reps.times { bool = prime( number ) }
if bool then
prime_count += 1
end
count += 1
else
exp = digits.to_i
end
}
}

puts Time.now - time
puts format("Of %d numbers, %d were prime.", count, prime_count )


-- Lua
function prime(n)
if n > 2 and n % 2 == 0 then
return false
end
for i = 3, math.floor(math.sqrt(n)), 2 do
if n % i == 0 then
return false
end
end
return true
end

reps = 10
io.write( "Testing each number ", reps, " times.\n" )
time = os.clock()
count, prime_count = 0, 0
for line in string.gmatch( [[
27 39, 79, 111, 115, 135, 187, 199, 219, 231, 235
28 57, 89, 95, 119, 125, 143, 165, 183, 213, 273
29 3, 33, 43, 63, 73, 75, 93, 99, 121, 133
30 35, 41, 83, 101, 105, 107, 135, 153, 161, 173
]] , "[^\n]+" ) do
exp = nil
for digits in string.gmatch( line, "%d+" ) do
if exp then
num = 2^exp - tonumber( digits )
for i = 1, reps do
bool = prime( num )
end
if bool then
prime_count = prime_count + 1
end
count = count + 1
else
exp = tonumber( digits )
end
end
end

print(os.clock() - time)
print( string.format("Of %d numbers, %d were prime.", count,
prime_count ) )

-----
Results on my old laptop:

Ruby 9.674 sec.
Lua 1.922
LuaJIT .210

Based upon these results and your experiment with optimize:

Speedup compared to pure Ruby
-----------------------------
optimize 4.397
Lua 5.033
LuaJIT 46.066