Thursday, April 05, 2007

ruby ช้า

ใน codenone คุณสุกรีตั้งโจทย์ Mandelbrot Set ไว้
แน่นอนเมื่อตั้งตัวเป็นผู้สนับสนุน ruby แล้ว
ก็ต้องทดลอง implement ด้วย ruby ดู (haskell เข้าคิวอยู่)

เริ่มแรกสุด ลอง implement algorithm โดยใช้ Datatype ที่มากับ ruby
require 'complex'
def is_mandel(z)
max = 30
cnt = 0
c = z
while (z.abs < 2 && cnt < max)
z = z ** 2 + c
cnt += 1
end
cnt == max ? 0 : cnt
end

สั้นดี ได้ใจความ
ทดลอง run ด้วย loop นี้
def bm()
step = 0.005
x = 0.0
while x < 1.0
y = 0.0
while y < 1.0
is_mandel(Complex.new(x,y))
y += step
end
x += step
end
end

ผลออกมาเกินห้ามใจ
นี่ขนาดคำนวณ แค่ 40000 จุด (200x200 pixel)

user system total real
complex 23.180000 0.260000 23.440000 ( 26.981269)


ปรับไปใช้ algorithm ใน wikipedia
def is_mandel2(x,y)
x0 = x
y0 = y
x2 = x*x
y2 = y*y

cnt = 0
max = 30

while (x2 + y2 < 4 && cnt < max)
y = 2*x*y + y0
x = x2 - y2 + x0

x2 = x*x
y2 = y*y

cnt += 1
end
cnt == max ? 0 : cnt
end


ผลลัพท์ ดีขึ้นหน่อย ดีกว่าเกือบ 4 เท่า
แต่ก็ยังช้าอยู่ดี

user system total real
wikipedia 5.440000 0.080000 5.520000 ( 6.913239)


สุดท้ายก็เปลี่ยนไปใช้ rubyinline
เพื่อจะเห็นแสงสว่างที่ปลายอุโมงค์บ้าง
inline do |builder|
builder.c "
int is_mandel3(double x, double y) {
double x0 = x;
double y0 = y;
double x2 = x * x;
double y2 = y * y;
int cnt = 0;
int max = 30;
while (x2 + y2 < 4 && cnt < max) {
y = 2*x*y + y0;
x = x2 - y2 + x0;
x2 = x*x;
y2 = y*y;
cnt++;
}
return cnt == max ? 0 : cnt;
}"

end

ผลลัพท์ที่ได้ ก็อย่างที่ทุกคนคงคาดไว้

user system total real
inline 0.220000 0.000000 0.220000 ( 0.257189)


Put the right man on the right job.
ภาษาก็เหมือนกัน

Related link from Roti

No comments: