2010-04-12 1 views
13

Я экспериментирую с фильтрацией через элементы параллельно. Для каждого элемента мне нужно выполнить вычисление расстояния, чтобы увидеть, достаточно ли близко к целевой точке. Не обращайте внимания на то, что структуры данных уже существуют для этого, сейчас я только начинаю эксперименты.Почему Clojure висит после выполнения моих расчетов?

В любом случае, я хотел запустить некоторые основные эксперименты, в которых я генерирую случайные векторы и фильтрую их. Вот моя реализация, которая делает все это

(defn pfilter [pred coll] 
    (map second 
    (filter first 
     (pmap (fn [item] [(pred item) item]) coll)))) 

(defn random-n-vector [n] 
    (take n (repeatedly rand))) 

(defn distance [u v] 
    (Math/sqrt (reduce + (map #(Math/pow (- %1 %2) 2) u v)))) 

(defn -main [& args] 
    (let [[n-str vectors-str threshold-str] args 
     n (Integer/parseInt n-str) 
     vectors (Integer/parseInt vectors-str) 
     threshold (Double/parseDouble threshold-str) 
     random-vector (partial random-n-vector n) 
     u (random-vector)] 
    (time (println n vectors 
     (count 
     (pfilter 
      (fn [v] (< (distance u v) threshold)) 
      (take vectors (repeatedly random-vector)))))))) 

код выполняется и возвращает то, что я ожидал, что параметр п (длина векторов), векторы (число векторов) и число векторов, которые ближе чем порог к целевому вектору. Я не понимаю, почему программы зависают в течение дополнительной минуты перед завершением.

Вот выход пробеге, который показывает ошибку

 
$ time lein run 10 100000 1.0 
    [null] 10 100000 12283 
    [null] "Elapsed time: 3300.856 msecs" 

real 1m6.336s 
user 0m7.204s 
sys 0m1.495s 

Любые комментарии о том, как фильтровать параллельно в целом также являются более чем желателен, так как я до сих пор не подтвердили, что pfilter на самом деле работает.

ответ

20

Чтобы убить потоки, поддерживающие threadpool, используемые pmap, вам необходимо позвонить shutdown-agents.

О pfilter, он должен работать, но работать медленнее, чем filter, так как ваш предикат прост. Параллелизация не является бесплатной, поэтому вам необходимо дать каждому потоку умеренно-интенсивные задачи, чтобы компенсировать многопоточные служебные данные. Перед их фильтрованием выложите партии.

+0

Ну ладно, спасибо. Я не собираюсь использовать его для простых дистанционных запросов, но это был более простой пример. Благодарю. – Thomas