मैं कुछ मामूली बड़ी DIMACS फ़ाइलों का निर्माण कर रहा हूं, हालांकि स्मृति उपयोग के नीचे उपयोग की गई विधि की तुलना में उत्पन्न फ़ाइलों के आकार की तुलना में बड़ी है, और मुझे उत्पन्न होने वाली कुछ बड़ी फ़ाइलों पर मैं out of memory
समस्याओं में भाग लेता हूं।राइटर मोनैड का उपयोग करके फ़ाइल लिखते समय मैं स्मृति समस्याओं से कैसे बचूं?
import Control.Monad.State.Strict
import Control.Monad.Writer.Strict
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Monad
import qualified Text.Show.ByteString as BS
import Data.List
main = printDIMACS "test.cnf" test
test = do
xs <- freshs 100000
forM_ (zip xs (tail xs))
(\(x,y) -> addAll [[negate x, negate y],[x,y]])
type Var = Int
type Clause = [Var]
data DIMACSS = DS{
nextFresh :: Int,
numClauses :: Int
} deriving (Show)
type DIMACSM a = StateT DIMACSS (Writer B.ByteString) a
freshs :: Int -> DIMACSM [Var]
freshs i = do
next <- gets nextFresh
let toRet = [next..next+i-1]
modify (\s -> s{nextFresh = next+i})
return toRet
fresh :: DIMACSM Int
fresh = do
i <- gets nextFresh
modify (\s -> s{nextFresh = i+1})
return i
addAll :: [Clause] -> DIMACSM()
addAll c = do
tell
(B.concat .
intersperse (B.pack " 0\n") .
map (B.unwords . map BS.show) $ c)
tell (B.pack " 0\n")
modify (\s -> s{numClauses = numClauses s + length c})
add h = addAll [h]
printDIMACS :: FilePath -> DIMACSM a -> IO()
printDIMACS file f = do
writeFile file ""
appendFile file (concat ["p cnf ", show i, " ", show j, "\n"])
B.appendFile file b
where
(s,b) = runWriter (execStateT f (DS 1 0))
i = nextFresh s - 1
j = numClauses s
मैं खंड के monadic इमारत रखने के लिए के बाद से यह बहुत आसान है करना चाहते हैं, लेकिन मैं स्मृति समस्या को दूर करने की जरूरत है। मैं उपर्युक्त प्रोग्राम को कैसे अनुकूलित कर सकता हूं ताकि यह बहुत अधिक स्मृति का उपयोग न करे?
तेज़ उत्तर के लिए धन्यवाद! मैंने वास्तव में आदिम ऑपरेशन के रूप में जोड़ा और 'addAll = mapM_ add' का उपयोग किया, लेकिन यह भी बदतर था। – HaskellElephant
हां, मुझे विश्वास है कि यदि आपके पास आलसी पर्याप्त लेखक नहीं है तो यह बदतर है; लेकिन अगर लेखक तुरंत परिणाम लिखेंगे तो बेहतर होना चाहिए। क्या आप यह देखने के लिए प्रोफाइलिंग करते हैं कि '[क्लॉज] 'या' बाइटस्ट्रिंग 'स्मृति को ओवरफ़्लो का कारण बनती है या नहीं? –
मैंने किया और यह 'बाइटस्ट्रिंग' है। – HaskellElephant