Biraz egzersiz olarak, haskell'de aşağıdaki kelime sayma programını yaptım. Bir metin dosyasında farklı kelimeleri sayar ve frekansları ile birlikte en sık 50 olanı çıkarır.Kelime sayma programımı, pürüzlü hileler kullanmadan daha hızlı hale getirmenin bir yolu var mı?
import qualified Data.Map as Map
import Data.List.Split
import Data.List
import Data.Ord
-- Count words
count = Map.toList . foldl' increment Map.empty
where
increment dict k = Map.insert k (1 + Map.findWithDefault 0 k dict) dict
-- Sort the counts
countAndSort = sortBy (flip $ comparing snd) . count
-- Pretty printing
pp :: Show a => [(String,a)] -> IO()
pp = putStrLn . foldl' format "" where
format text (x,y) = text ++ "\n" ++ x ++ "\t" ++ show y
main = readFile "pg13951.txt" >>= pp . take 50 .countAndSort . splitOn " "
sorun bunun bir değişken dict ile benim piton uygulanması göre 16 kat daha yavaş olduğunu olmasıdır:
def increment(dic,word):
dic[word] = dic.get(word,0) + 1
return dic
print sorted(reduce(increment,open("pg13951.txt").read().split(),{}).items(),key=lambda e:-e[1])[:50]
Sorun ghc constanstly yeni haritalar zaman realocating gerçeğine bağlı olduğunu düşünüyorum Aynı olanı tekrar tekrar kullanabilir. Çalışma zamanı statitistics tahsisleri bir sürü gösterir:
$ ghc -rtsopts count.hs
$ ./count +RTS -sstderr
de 7682
et 4423
la 4238
<snip>
d'Artagnan 511
M. 502
c'est 443
d'Artagnan, 443
705,888,048 bytes allocated in the heap
655,511,720 bytes copied during GC
139,823,800 bytes maximum residency (10 sample(s))
1,049,416 bytes maximum slop
287 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1366 colls, 0 par 2.16s 2.26s 0.0017s 0.0072s
Gen 1 10 colls, 0 par 2.86s 3.09s 0.3093s 1.5055s
INIT time 0.00s ( 0.00s elapsed)
MUT time 3.18s ( 3.36s elapsed)
GC time 5.02s ( 5.36s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 8.20s ( 8.72s elapsed)
%GC time 61.2% (61.4% elapsed)
Alloc rate 221,831,366 bytes per MUT second
Productivity 38.8% of total user, 36.5% of total elapsed
Sorum şu: Bu programı yapmak için bir yolu yoktur böyle, IO monad çalışan değişken veri yapılarını kullanarak kirli hileler başvurmadan, daha iyi performans, vb. ?
Not: veri dosyası aşağıdaki adresten bulabilirsiniz: Burada http://www.gutenberg.org/cache/epub/13951/pg13951.txt
Eğer Data.Map.Strict kullanırsanız nasıl performans gösteriyor? Data.Map kaynağına bakarsanız, varsayılan uygulamanın Data.Map.Lazy olduğunu ve Data.Map.Strict'i kullanmanız gerektiğini görürsünüz. "En sonunda depolanan tüm değerlere ihtiyacınız olacaktır" ve "Depolanan değerler" tembel olarak hesaplanacak büyük sanal veri yapılarını temsil etmeyin ". Davanızı tam olarak açıklayan bana ait. – itsbruce
@itsbruce: Denedim ama çok değişmedi. @ Shang'ın yanıtına göre, en büyük sorunun Data.Text yerine 'String 'kullandığını düşünüyorum. Bu gece daha fazla test edeceğim. –
koduna da paralel olarak, wordcount bir mapReduce tarzı hesaplama için tipik bir örnektir; Ayrıca, '-threaded' ile derlemeyi deneyebilir ve '+ RTS -N 'ile çalışarak makinenizde daha fazla çekirdek kullanmak için çalışabilirsiniz –
jev