質問

Refuctors Libraryでマッピング/縮小しているのは、通常のマップ/削減よりも悪い性能を持っていますか?

user=> (time (reduce + (map inc (range 100000000))))
"Elapsed time: 14412.627966 msecs"
5000000050000000

user=> (time (reduce + (r/map inc (range 100000000))))
... (C-c)

user=> (time (r/reduce + (r/map inc (range 100000000))))
....(C-c)
.

私は2つの後者の殺害があると無期限に長くかかる。ここで何が悪いの?

編集: 他の言語も同様の問題もあります。Scalaは百万人だけで壊れているようです。 Scala Parallel CollectionsがOutOfMemoryErrorを発生させることがあるのはなぜですか?。Clojure Defuctorsは100万人で通常より速いです。

役に立ちましたか?

解決

@ a-webbの答えを補完するために、これはコンパイラのバグと、本当に修正するための関与のものです。(詳細については、この記事を参照してください。

問題を回避するもう1つの方法は、 FUSE を使用することです。:

(defn once-seq
  "Returns a sequence on which seq can be called only once."
  [coll]
  (let [a (atom coll)]
    (reify clojure.lang.Seqable
      (seq [_]
        (let [coll @a]
          (reset! a nil)
          (seq coll))))))
.

、次に

=> (time (r/reduce + (r/map inc (once-seq (range 100000000)))))
"Elapsed time: 3692.765 msecs"
5000000050000000
.

他のヒント

メモリが使い果たされているので、性能は停止に研削されています。待っている場合は、メモリエラーが発生する可能性が最も高いです。減速機を作成すると、コレクションの先頭をクロージャーに保持します。したがって、膨大な遅延シーケンスは実現されるにつれてメモリを上昇させます。

これが何が起こっているのか、蒸留

user=> (def n 100000000)
#'user/n

user=> (time (dorun (range n)))
"Elapsed time: 12349.034702 msecs"
.

今も同じですが、クロージャー内から

user=> (defn foo [x] (fn [f] (f x)))
#'user/foo

user=> (time ((foo (range n)) dorun))
OutOfMemoryError GC overhead limit exceeded ... (sometime later)
.

と比較してください
(time (do (doall (range n)) nil))
OutOfMemoryError GC overhead limit exceeded ... (sometime later)
.

還元剤の疑わしい閉鎖

user=> (source r/folder)
(defn folder
  "Given a foldable collection, [...]"
  {:added "1.5"}
  ([coll xf]
     (reify
      clojure.core.protocols/CollReduce
      (coll-reduce [_ f1]
                   (clojure.core.protocols/coll-reduce coll (xf f1) (f1)))
   ...
.

Christophe Grand 怠惰な方法で減速機を作成する方法については、

縮小剤は遅延リストでは実際にはうまくいかないが、通常の減少は行います。

再契約者のうちに本当の利益を得るために、あなたは非怠惰なコレクションを必要とします。ベクトルとあなたは減少の代わりに折り目を使う必要があります。

 (def v (into [] (range 10000000)))
 (time (reduce + (map inc v)))
 ;; "Elapsed time: 896.79 msecs"
 (time (reduce + (r/map inc v)))
 ;; "Elapsed time: 671.947 msecs" 
 (time (r/fold + (r/map inc v)))
 ;; "Elapsed time: 229.45 msecs"
.

縮小剤は、大きなデータのチャンクを必要とするフォーク/結合フレームワークで動作します。怠惰な(チャンクされた)シーケンスでは、これらの大きなチャンクを持っていませんので、フォーク/結合はうまく機能できません。

概念を説明する還元剤では豊富なHickeyによる話があります。 https://vimeo.com/45561411

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top