Сбой программы при попытке создать несколько потоков - PullRequest
3 голосов
/ 09 мая 2011

У меня есть следующая программа:

module Main where

import System (getArgs)
import Control.Concurrent
import Control.Monad

spawn left id = do
   right <- newEmptyMVar
   forkIO (thread id left right) 
   return right

thread id left right = go 
   where go = do l <- takeMVar left
                 putStrLn (show id)
                 putMVar right ()

main = do
   args <- getArgs
   if null args then
      putStrLn "Arguments not supplied"
   else do
      initial <- newEmptyMVar
      final <- foldM spawn initial [1..(read (head args))]
      putMVar initial ()
      takeMVar final

Как видите, он просто создает несколько потоков: каждый поток печатает целое число, но второй поток ждет первого перед печатью, третийждет второго и тд.Давайте не будем обсуждать полезность этой программы (это всего лишь упражнение).

Теперь, когда я пытаюсь создать миллион потоков, программа убивается с помощью SIGKILL.Я хотел бы знать причину этого.Это из-за слишком большого количества MVars?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 09 мая 2011

Согласно документам GHC , начальный размер стека для каждого потока по умолчанию составляет 1 КБ, и он может увеличиваться по требованию до 8 МБ на поток.

Вы можете настроить эти числа с помощьюиспользуя параметры RTS -k и -K, например:

$ ./Threads 1000000 +RTS -k512 -K1K -s

Ваша программа работает нормально на моей системе (64-разрядная с 6 ГБ ОЗУ), но на пике она потребляет более 2 ГБ.

   4,743,629,168 bytes allocated in the heap
   4,368,720,328 bytes copied during GC
   1,043,256,808 bytes maximum residency (11 sample(s))
     221,352,512 bytes maximum slop
            2413 MB total memory in use (0 MB lost due to fragmentation)

  Generation 0:  8707 collections,     0 parallel,  1.46s,  1.59s elapsed
  Generation 1:    11 collections,     0 parallel,  1.72s,  3.16s elapsed

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    5.86s  ( 15.76s elapsed)
  GC    time    3.18s  (  4.75s elapsed)
  EXIT  time    0.08s  (  0.08s elapsed)
  Total time    9.12s  ( 20.59s elapsed)

  %GC time      34.9%  (23.1% elapsed)

  Alloc rate    798,590,769 bytes per MUT second

  Productivity  65.1% of total user, 28.9% of total elapsed

./Threads 1000000 +RTS -K1K -s  9.12s user 3.92s system 62% cpu 20.815 total
2 голосов
/ 09 мая 2011

Каждый созданный поток требует своего собственного программного стека. На самом деле я не знаю, какой размер стека использует Haskell для своих потоков, но если его размер составляет 4 КБ (что на самом деле будет очень мало), то это будет 4 ГБ только для миллиона стеков. Если вы работаете на 32-битной машине, это вся адресуемая память, так что это явно не сработает. А типичный размер стека больше похож на мегабайт!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...