9

問題

Haskell で多値出力関数をシミュレートしたい。Haskell コードが生成されます (手書きではありません)。これは重要な情報です。以下を参照してください。

これはもちろん、次のように関数からタプルを返すことで簡単に実行できます。

f x y = (x+y, x-y)

しかし、そのような関数を使用するときは、それが返すタプルの種類を知る必要があります:

...
(out_f_1, out_f_2)          = f a b
(out_g_1, out_g_2, out_g_3) = g out_f_1
...

など...しかし、コードを生成している間、fの出力のタイプがわからないので、現在、Data.List.Selectパッケージを使用して上記をシミュレートしています:

import Data.List.Select
...
out_f = f a b
out_g = g (sel1 outf)
...

問題はパフォーマンスです。私のテスト プログラムでは、使用するバージョンは、Data.List.Select手動で記述したバージョンよりも 2 倍遅くなります。

andData.List.Selectを使用して記述されているため、これは非常に明白な状況です (私が間違っていない場合)。( http://hackage.haskell.org/packages/archive/tuple/0.2.0.1/doc/html/src/Data-Tuple-Select.html#sel1 )classesinstances

質問

Data.List.Select手動で作成されたものと同じくらい高速になるようにバージョン (を使用する) を何らかの方法でコンパイルすることは可能ですか?

コンパイラーへの切り替えが必要だと思います。これにより、使用ごとにクラスとインターフェースを「インスタンス化」するように指示されます (C++ のテンプレートのようなもの)。

ベンチマーク

Test1.hs:

import qualified Data.Vector as V
import System.Environment
b :: Int -> Int
b x = x + 5
c x = b x + 1
d x = b x - 1
a x = c x + d x
main = do
   putStrLn "Starting..."
   args <- getArgs
   let iternum = read (head args) :: Int in do
      putStrLn $ show $ V.foldl' (+) 0 $ V.map (\i -> a (iternum-i))
         $ V.enumFromTo 1 iternum
      putStrLn "Done."

でコンパイルghc -O3 Test1.hs

Test2.hs:

import qualified Data.Vector as V
import Data.Tuple.Select
import Data.Tuple.OneTuple

import System.Environment
b x = OneTuple $ x + 5
c x = OneTuple $ (sel1 $ b x) + 1
d x = OneTuple $ (sel1 $ b x) - 1
a x = OneTuple $ (sel1 $ c x) + (sel1 $ d x)
main = do
   putStrLn "Starting..."
   args <- getArgs
   let iternum = read (head args) :: Int in do
      putStrLn $ show $ V.foldl' (+) 0 $ V.map (\i -> sel1 $ a (iternum-i))
         $ V.enumFromTo 1 iternum
      putStrLn "Done."

でコンパイルghc -O3 Test2.hs

結果

time ./Test1 10000000 = 5.54 s
time ./Test2 10000000 = 10.06 s
4

2 に答える 2

3

よくわかりませんが、 http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/pragmas.html#specialize-pragmaを試す価値があるかもしれません

于 2013-07-24T13:03:08.120 に答える