私はHaskellで書かれたプログラムの驚くべき性能について多くのことを聞き、いくつかのテストをしたかったのです。だから、純粋なC言語で書かれたものと性能を比較するだけの行列演算のライブラリを書いた。 まず、500000行列の乗算性能をテストしたところ、それは終わりがないことに気づいた。メモリ不足で10分後に例外が発生しました)!私は、怠惰を取り除くために管理したhaskellをもう少し調べた後、私が得た最良の結果は、Cでの同等のものより約20倍遅くなっています。 質問:以下のコードを見直して、もう少し改善されるでしょうか? 20回もまだ私は少し失望しています。haskell行列実装の性能
import Prelude hiding (foldr, foldl, product)
import Data.Monoid
import Data.Foldable
import Text.Printf
import System.CPUTime
import System.Environment
data Vector a = Vec3 a a a
| Vec4 a a a a
deriving Show
instance Foldable Vector where
foldMap f (Vec3 a b c) = f a `mappend` f b `mappend` f c
foldMap f (Vec4 a b c d) = f a `mappend` f b `mappend` f c `mappend` f d
data Matr a = Matr !a !a !a !a
!a !a !a !a
!a !a !a !a
!a !a !a !a
instance Show a => Show (Matr a) where
show m = foldr f [] $ matrRows m
where f a b = show a ++ "\n" ++ b
matrCols (Matr a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3)
= [Vec4 a0 a1 a2 a3, Vec4 b0 b1 b2 b3, Vec4 c0 c1 c2 c3, Vec4 d0 d1 d2 d3]
matrRows (Matr a0 b0 c0 d0 a1 b1 c1 d1 a2 b2 c2 d2 a3 b3 c3 d3)
= [Vec4 a0 b0 c0 d0, Vec4 a1 b1 c1 d1, Vec4 a2 b2 c2 d2, Vec4 a3 b3 c3 d3]
matrFromList [a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3]
= Matr a0 b0 c0 d0
a1 b1 c1 d1
a2 b2 c2 d2
a3 b3 c3 d3
matrId :: Matr Double
matrId = Matr 1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
normalise (Vec4 x y z w) = Vec4 (x/w) (y/w) (z/w) 1
mult a b = matrFromList [f r c | r <- matrRows a, c <- matrCols b] where
f a b = foldr (+) 0 $ zipWith (*) (toList a) (toList b)
あなたの行列 'mult'は戻って行列に行列、リストとの間で表現を変えています。これにより、2行のコードで計算を行うことができますが、非常に遅くなります。 –
@stephen tetley:必ずしもそうではありません。コンパイラは最近、インライン展開と森林破壊の面でかなり優れているため、スマートコンパイラは中間リストを削除します。私のテストでは、この実装は、「高速」手書きの展開されていない乗算と比べて、非常に遅くはありません(わずか1.5倍の遅さです)。 UPD:私の間違いは、実際には倍の行列に対して6倍遅くなります。 –
トロールのラベルを付ける危険があるので、私はあなたがこれらのテストで探しているような結果を見つけることはないと思います。 Haskellの優れた点は、Cに比べて読みやすさと表現力が高く、 'STM'や' parallel'などの高度なライブラリであり、ほとんどの場合に比べて並列化が非常に簡単になります他の言語。純粋な数値作業のために、HaskellのパフォーマンスがCの実装に勝ることは非常に困難です。 –