2015-11-24 2 views
0

Je voulais apprendre Clojure et j'ai commencé avec un générateur de Mandelbrot en utilisant quil, je l'ai eu à travailler - mais il faut du temps pour générer des images et est un gros tas de ressources. Tout conseil pour la rendre plus rapide ou si vous repérez des parties non-clojure-esque de mon code.Augmenter l'efficacité dans le générateur Clojure Mandelbrot

Core.clj

(ns frac.core 
    (:require [quil.core :as q]) 
    (:require [frac.complex :refer :all])) 

(def scale (atom 0.01)) 
(def xoff (atom -200)) 
(def yoff (atom -200)) 
(def its 50) 

(defn mandelbrot [r i] 
(count (take its (take-while #(<= (modu %) 2) (iterate #(add (mul % %) [r i]) [r i]))))) 

(defn gen [] 
    (let [p (q/pixels) 
     w (q/width) 
     h (q/height)] 
    (doseq [x (range w) y (range h)] 
     (let [m (mandelbrot (* @scale (+ x @xoff)) (* @scale (+ y @yoff))) 
      c (if (= m its) 0 m)] 
     (aset p (+ x (* y w)) (q/color (* 1.5 c) (* 4 c) (* 5.2 c)))))) 
    (q/update-pixels)) 

(defn setup [] 
    (gen)) 

(defn draw []) 

(defn click [] 
    (swap! xoff #(+ (q/mouse-x) (- (/ (q/width) 2)) %)) 
    (swap! yoff #(+ (q/mouse-y) (- (/ (q/height) 2)) %)) 
    (gen)) 

(defn wheel [z] 
    (swap! scale #(if (pos? z) (* 1.1 %) (* 0.9 %))) 
    (prn @scale) 
    (gen)) 

(q/defsketch example 
    :title "Mandel" 
    :setup setup 
    :draw draw 
    :size [400 400] 
    :mouse-clicked click 
    :mouse-wheel wheel) 

(defn -main [& args]) 

Complex.clj

(ns frac.complex) 

(defn mul [z1 z2] 
    (let [r1 (first z1) 
     i1 (second z1) 
     r2 (first z2) 
     i2 (second z2)] 
    [(- (* r1 r2) (* i1 i2)) (+ (* r1 i2) (* r2 i1))])) 

(defn add [z1 z2] 
    (let [r1 (first z1) 
     i1 (second z1) 
     r2 (first z2) 
     i2 (second z2)] 
    [(+ r1 r2) (+ i1 i2)])) 

(defn modu [z] 
    (let [r (first z) 
     i (second z)] 
    (Math/sqrt (+ (* r r) (* i i))))) 
+0

peut-être pas liée à la performance, mais vous pourriez envisager d'utiliser la déstructuration avec votre mul/add fn (par exemple 'defn mul [[r1 i1] [r2 i2]]' pour une lisibilité plus facile – cfrick

+3

Ceci devrait être déplacé vers [Code Review] (http://codereview.stackexchange.com/) –

+0

Je ne suis pas Clojure, mais pour être efficace, pour chaque génération, précalculer deux tableaux 1-D mettant à l'échelle les positions des pixels sur la carte. Pour réduire le temps d'exécution de chaque itération, il n'est pas nécessaire de prendre une racine carrée pour trouver le module Au lieu de comparer le module avec une "valeur d'échappement" de dis 2, comparez son carré avec 4. Et comme vous le souhaitez x^2 et y^2 (au carré) pour chaque itération, ne les calculez pas deux fois.Essayez de ne pas appeler les fonctions depuis la boucle d'itération, et notez que vous n'avez même pas besoin de fonctions complexes. –

Répondre

0

Essayez de définir ceci:

(set! *unchecked-math* :warn-on-boxed) 

et supprimer tous les avertissements. Utilisez les astuces de type si nécessaire.