I'm trying to convert Python -> CL for a program that calculates x,y color values for the Mandelbrot set.
The python version takes about 1.2 seconds to complete. I tried using the CL cookbook for performance tips, but my CL attempt is taking an eternity, so I'm doing something very wrong.
How can I improve its performance?
Python:
import time
t0 = time.time()
WIDTH = 800
HEIGHT = 600
PIXELS = [[None] * WIDTH for _ in range(HEIGHT)]
# Plot window
RE_START = -2
RE_END = 1
IM_START = -1
IM_END = 1
MAX_ITER = 80
def mandelbrot(c):
z = 0
n = 0
while abs(z) <= 2 and n < MAX_ITER:
z = z*z + c
n += 1
return n
for x in range(0, WIDTH):
for y in range(0, HEIGHT):
c = complex(RE_START + (x / WIDTH) * (RE_END - RE_START),
IM_START + (y / HEIGHT) * (IM_END - IM_START))
m = mandelbrot(c)
color = 255 - int(m * 255 / MAX_ITER)
PIXELS[y][x] = color
t1 = time.time()
print(t1-t0)
CL (SBCL):
(require :sb-sprof)
(declaim (optimize speed))
(defparameter *WIDTH* 800)
(defparameter *HEIGHT* 600)
(defparameter *PIXELS* (make-array `(,*WIDTH* ,*HEIGHT*) :initial-element 0))
(defparameter *MAX-ITER* 80)
(defparameter *RE-START* -2)
(defparameter *RE-END* 1)
(defparameter *IM-START* -1)
(defparameter *IM-END* 1)
(defun coord-to-complex (x y)
(complex (+ *RE-START* (* (/ x *WIDTH*) (- *RE-END* *RE-START*)))
(+ *IM-START* (* (/ y *HEIGHT*) (- *IM-END* *IM-START*)))))
(defun mandelbrot (c)
(let ((z 0)
(n 0))
(loop while (and (<= (abs z) 2) (< n *MAX-ITER*))
do (setf z (+ (* z z) c)
n (1+ n)))
n))
(defun calculate-mandelbrot (array)
(loop for x from 0 below *WIDTH* do
(loop for y from 0 below *HEIGHT* do
(let* ((c (coord-to-complex x y))
(m (mandelbrot c))
(color (- 255 (/ 255 (* m *MAX-ITER*)))))
(setf (aref array x y) color)))))
(sb-sprof:with-profiling (:max-samples 1000
:report :flat
:loop nil)
(calculate-mandelbrot *PIXELS*))