Профилирование программы на Haskell

У меня есть фрагмент кода, который многократно выбирает из распределения вероятностей, используя sequence. Морально это выглядит примерно так:

sampleMean :: MonadRandom m => Int -> m Float -> m Float
sampleMean n dist = do
  xs <- sequence (replicate n dist)
  return (sum xs)

Разве что немного сложнее. Фактический код, который меня интересует, — это функция likelihoodWeightingв этом репозитории Github .

Я заметил, что время выполнения нелинейно зависит от n. В частности, когда nпревышает определенное значение, он достигает предела памяти, и время работы резко увеличивается. Я не уверен, но думаю, это потому, что sequenceсоздает длинный список переходников, которые не обрабатываются до вызова sum.

Как только я преодолел около 100 000 образцов, программа замедлилась до минимума. Я хотел бы оптимизировать это, (я чувствую, что 10 миллионов выборок не должны быть проблемой ), поэтому я решил профилировать это -, но у меня возникли небольшие проблемы с пониманием вывода профилировщика.


Профилирование

Я создал короткий исполняемый файл в файле main.hs, который запускает мою функцию со 100 000 выборок. Вот результат выполнения

$ ghc -O2 -rtsopts main.hs
$./main +RTS -s

Первое, что я заметил -, он выделяет около 1,5 ГБ кучи и тратит 60% своего времени на сборку мусора. Это вообще показатель слишком большой лени?

 1,377,538,232 bytes allocated in the heap
 1,195,050,032 bytes copied during GC
   169,411,368 bytes maximum residency (12 sample(s))
     7,360,232 bytes maximum slop
           423 MB total memory in use (0 MB lost due to fragmentation)

Generation 0:  2574 collections,     0 parallel,  2.40s,  2.43s elapsed
Generation 1:    12 collections,     0 parallel,  1.07s,  1.28s elapsed

INIT  time    0.00s  (  0.00s elapsed)
MUT   time    1.92s  (  1.94s elapsed)
GC    time    3.47s  (  3.70s elapsed)
RP    time    0.00s  (  0.00s elapsed)
PROF  time    0.23s  (  0.23s elapsed)
EXIT  time    0.00s  (  0.00s elapsed)
Total time    5.63s  (  5.87s elapsed)

%GC time      61.8%  (63.1% elapsed)

Alloc rate    716,368,278 bytes per MUT second

Productivity  34.2% of total user, 32.7% of total elapsed

Вот результаты из

$./main +RTS -p

В первый раз, когда я запустил это, оказалось, что одна функция вызывалась неоднократно, и оказалось, что я могу запомнить ее, что ускорило процесс в 2 раза. Однако это не решило проблему утечки пространства.

COST CENTRE           MODULE                no. entries  %time %alloc   %time %alloc

MAIN                  MAIN                    1        0   0.0    0.0   100.0  100.0
 main                 Main                  434        4   0.0    0.0   100.0  100.0
  likelihoodWeighting AI.Probability.Bayes  445        1   0.0    0.3   100.0  100.0
   distributionLW     AI.Probability.Bayes  448        1   0.0    2.6     0.0    2.6
   getSampleLW        AI.Probability.Bayes  446   100000  20.0   50.4   100.0   97.1
    bnProb            AI.Probability.Bayes  458   400000   0.0    0.0     0.0    0.0
    bnCond            AI.Probability.Bayes  457   400000   6.7    0.8     6.7    0.8
    bnVals            AI.Probability.Bayes  455   400000  20.0    6.3    26.7    7.1
     bnParents        AI.Probability.Bayes  456   400000   6.7    0.8     6.7    0.8
    bnSubRef          AI.Probability.Bayes  454   800000  13.3   13.5    13.3   13.5
    weightedSample    AI.Probability.Bayes  447   100000  26.7   23.9    33.3   25.3
     bnProb           AI.Probability.Bayes  453   100000   0.0    0.0     0.0    0.0
     bnCond           AI.Probability.Bayes  452   100000   0.0    0.2     0.0    0.2
     bnVals           AI.Probability.Bayes  450   100000   0.0    0.3     6.7    0.5
      bnParents       AI.Probability.Bayes  451   100000   6.7    0.2     6.7    0.2
     bnSubRef         AI.Probability.Bayes  449   200000   0.0    0.7     0.0    0.7

Вот куча профиля. Я не знаю, почему он утверждает, что время выполнения составляет 1,8 секунды -, этот запуск занял около 6 секунд.

enter image description here

Может ли кто-нибудь помочь мне интерпретировать вывод профилировщика -, т. е. определить, где находится узкое место, и дать предложения о том, как ускорить процесс?

23
задан Chris Taylor 22 July 2012 в 00:15
поделиться