Skip to content

Instantly share code, notes, and snippets.

@rdp
Created June 20, 2012 17:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rdp/2961231 to your computer and use it in GitHub Desktop.
Save rdp/2961231 to your computer and use it in GitHub Desktop.
mandel.rb
# originally from http://shootout.alioth.debian.org/u32q/program.php?test=mandelbrot&lang=jruby&id=2
PAD = "\\\\__MARSHAL_RECORD_SEPARATOR__//" # silly, but works
class Worker
attr_reader :reader
def initialize(enum, index, total, &block)
@enum = enum
@index = index
@total = total
@reader, @writer = IO.pipe
if RUBY_PLATFORM == "java"
@t = Thread.new do
self.execute(&block)
end
else
@p = Process.fork do
@reader.close
self.execute(&block)
@writer.close
end
@writer.close
end
end
attr_accessor :t
def execute(&block)
(0 ... @enum.size).step(@total) do |bi|
idx = bi + @index
if item = @enum[idx]
res = yield(item)
@writer.write(Marshal.dump([idx, res]) + PAD)
end
end
@writer.write(Marshal.dump(:end) + PAD)
end
end
def parallel_map(enum, worker_count = 8, &block)
count = [enum.size, worker_count].min
Array.new(enum.size).tap do |res|
workers = (0 ... count).map do |idx|
Worker.new(enum, idx, count, &block)
end
ios = workers.map { |w| w.reader }
while ios.size > 0 do
sr, sw, se = IO.select(ios, nil, nil, 0.01)
if sr
sr.each do |io|
buf = ""
while sbuf = io.readpartial(4096)
buf += sbuf
break if sbuf.size < 4096
end
msgs = buf.split(PAD)
msgs.each do |msg|
m = Marshal.load(msg)
if m == :end
ios.delete(io)
else
idx, content = m
res[idx] = content
end
end
end
end
end
workers.each{|t| t.t.join}
end
end
$size = (ARGV[0] || 100).to_i
csize = $size - 1
puts "P4"
puts "#{$size} #{$size}"
set = (0 ... $size).to_a
results = parallel_map(set, 8) do |y|
res = ""
byte_acc = 0
bit_num = 0
ci = (2.0 * y / $size) - 1.0
$size.times do |x|
zrzr = zr = 0.0
zizi = zi = 0.0
cr = (2.0 * x / $size) - 1.5
escape = 0b1
50.times do
tr = zrzr - zizi + cr
ti = 2.0 * zr * zi + ci
zr = tr
zi = ti
# preserve recalculation
zrzr = zr * zr
zizi = zi * zi
if zrzr + zizi > 4.0
escape = 0b0
break
end
end
byte_acc = (byte_acc << 1) | escape
bit_num += 1
if (bit_num == 8)
res += byte_acc.chr
byte_acc = 0
bit_num = 0
elsif (x == csize)
byte_acc <<= (8 - bit_num)
res += byte_acc.chr
byte_acc = 0
bit_num = 0
end
end
res
end
print 'done'#results.join
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment