2011-01-13 8 views
5

Sto cercando di capire come ottimizzare un po 'di codice. Eccolo:le funzioni inline appaiono ancora nel file .prof


{-# OPTIONS_GHC -funbox-strict-fields #-} 

data Vec3 a = Vec3 !a !a !a 

vx :: Vec3 a -> a 
vx (Vec3 x _ _) = x 
{-# SPECIALIZE INLINE vx :: Vec3 Double -> Double #-} 

vy :: Vec3 a -> a 
vy (Vec3 _ y _) = y 
{-# SPECIALIZE INLINE vy :: Vec3 Double -> Double #-} 

vz :: Vec3 a -> a 
vz (Vec3 _ _ z) = z 
{-# SPECIALIZE INLINE vz :: Vec3 Double -> Double #-} 


dot :: (Num a) => Vec3 a -> Vec3 a -> a 
dot u v = (vx u * vx v) + (vy u * vy v) + (vz u * vz v) 
{-# SPECIALIZE INLINE dot :: Vec3 Double -> Vec3 Double -> Double #-} 


type Vec3D = Vec3 Double 

-- just make a bunch of vecs to measure performance 

n = 1000000 :: Double 

v1s = [Vec3 x y z | (x, y, z) <- zip3 [1 .. n] [2 .. n + 1] [3 .. n + 2]] 
     :: [Vec3D] 

v2s = [Vec3 x y z | (x, y, z) <- zip3 [3 .. n + 2] [2 .. n + 1] [1 .. n]] 
     :: [Vec3D] 


dots = zipWith dot v1s v2s :: [Double]  
theMax = maximum dots :: Double 
main :: IO() 
main = putStrLn $ "theMax: " ++ show theMax 

Quando compilo con GHC 6.12.1 (Ubuntu Linux su una macchina i486)

ghc --make -O2 Vec.hs -Prof -auto -all -fforce-ReComp

ed eseguire

Vec + RTS -p

Guardando il file Vec.prof,


COST CENTRE     MODULE    %time %alloc 

v2s       Main     30.9 36.5 
v1s       Main     27.9 31.3 
dots       Main     27.2 27.0 
CAF       GHC.Float    4.4 5.2 
vy        Main     3.7 0.0 
vx        Main     2.9 0.0 
theMax       Main     2.2 0.0 

vedo che la funzione VX e VY prendono una parte significativa del tempo.

Perché è quello? Ho pensato che il pragma SPECIALIZE INLINE avrebbe reso quelle funzioni vanno via.

Quando si utilizza un non-polimorfica

data Vec3D = Vec3D {vx, vy, vz :: !Double} deriving Show 

le funzioni vx, vy, vz non mostrano come centro di costo.

+1

Hai davvero guardato al centro? Prova a compilare con '-ddump-core' e vedi cosa è successo. – fuz

risposta

2

Sospetto che si tratti di un effetto collaterale dell'utilizzo di -auto-all, che inibisce molte ottimizzazioni che GHC normalmente eseguirà, inclusa l'inlining. Sospetto che la differenza nella tua versione non polimorfica sia in realtà dovuta a vx, vy e vz che viene definita tramite la sintassi del record piuttosto che a causa del polimorfismo (ma potrei sbagliarmi).

Invece di utilizzare -auto-all, provare ad aggiungere un elenco di esportazione al modulo e compilare con "-auto" o impostare manualmente i centri di costo tramite i prcmas SCC. Di solito uso i prcmas di SCC in ogni caso perché spesso desidero impostarli su funzioni let-bound, che -auto-all non farà.

2

Non riesco a capire come fare commenti alle risposte, quindi sto facendo commenti in questa risposta.

In primo luogo, grazie per le vostre risposte.

FUZxxl: ho provato -ddump-core e ho ricevuto un messaggio di errore che -ddump-core era un flag non riconosciuto. Forse intendevi -ddump-simpl, che il libro consigliato da World World Haskell, ma temo di non sapere come leggere l'output. Ho cercato nel file di output "vx", ecc., Ma non li ho mai visti. Credo che dovrei imparare a leggere il nucleo. Ci sono delle buone guide per questo?

John: Secondo flag reference documentation del GHC, se sto leggendo correttamente, sia -Auto e -auto-tutto, si suppone aggiungi _scc_s alle funzioni non marcata linea. Per vedere se -auto avrebbe funzionato per me, ho creato un altro test case in cui il codice Vec3 era in un file/modulo separato, con Vec3 (Vec3), vx, vy, vz e punto esportati. Ho importato questo modulo in un file Main.hs. Compilando questi con -auto, ho ancora visto vx, vy, vz nel file .prof.

Re: il commento che la differenza potrebbe essere dovuta a registrare la sintassi, invece di polimorfismo, credo che la differenza è più probabile a causa di polimorfismo, perché quando ho definito

data Vec3 a = Vec3 {vx, vy, vz :: !a} 

vx, vy e vz ancora mostrato nel file .prof.

Tad

+0

Dovresti prendere in considerazione l'utilizzo di un account reale per le tue domande. Se possiedi un account di questo tipo, puoi lasciare commoents prima alle tue domande e poi a qualsiasi cosa quando la tua reputazione è abbastanza alta. – fuz

+0

Grazie per il consiglio. L'ho fatto ora. – Tad