2012-10-16 32 views
2

我有一個函數f,它返回一個大的整數。接近尾聲的程序必須加起來所有返回的值f。此計算機的物理內存太有限,無法存儲所有返回的值f。所以我需要把它放到文件緩衝區中。 TVars能夠處理整數嗎?是否有解決方案,我可以拋出所有返回的值f?另外,單獨的線程能夠同時讀取並緩衝它嗎?在STMTVar中有一個整數是個好主意嗎?

+0

您是否需要存儲f的所有值以供將來參考或將其添加?那裏的線程只是爲了計算f值還是出於其他原因? – AndrewC

+1

你問了很多問題,很難一下子回答所有問題。如果你向我們展示了一些不能做你想做的事情的代碼,那會更容易。 – HaskellElephant

+0

當這些線程計算的結果不會全部適合內存時,使用許多線程聽起來很難控制。你如何阻止所有的線程同時產生結果?你真的需要線程嗎?如果是這樣,也許一個線程池會很好。 – augustss

回答

1

你的問題並不清楚。根據我的理解,您需要存儲函數f在程序運行過程中返回的所有結果,並且由於存在大量此類結果,因此您希望將這些結果存儲在文件中。因爲一旦計算出來就實際存儲每個結果的效率會很低,所以你想實現一種緩衝形式。

如果是這種情況,你可以使用類似Chan的東西,例如它是一個無界阻塞的FIFO隊列。爲了回答你的一個擔憂,這個結構是專門爲多線程併發訪問而設計的。

因此,您可以在您要調用f的地方運行主程序,並且對於每次調用,您還可以將結果插入到Chan中。你也會產生另一個線程,它會持續從Chan讀取並將結果寫入文件。

現在,如果主線程(調用f的線程)的速率遠高於其他線程將結果存儲在磁盤上的速率,那麼您將回到原來的問題,其中結果堆積在陳,你在某些時候仍然不滿。對於這種特殊情況,您可以使用類似BoundedChan這類似Chan的功能,但當通道已滿時將在插入時阻止。在這種情況下,主線程可能不得不等待寫線程將結果存儲在磁盤上,但是您可以保證永遠不會用f的許多結果填充內存。

我們實際上可以爲此構建一個很好的抽象。我們可以想象一個函數traceable,給定函數f和存儲值的方法給了我們一個返回與f相同結果的函數,但是作爲副作用,它還存儲了結果供以後分析。

traceable :: (a -> b) -> (b -> IO()) -> (a -> IO b) 
traceable f store = \x -> do 
    let result = f x 
    store result 
    return result 

在你的情況下,程序會是這個樣子:

f :: Int -> Int 
f = ... -- implementation of f here 

main = do 
    ch <- newChan 
    traceableF = traceable f (writeChan ch) 
    forkIO $ resultWriter ch 
    -- the main program which calls traceableF here ... 

resultWriter :: Chan Int -> IO() 
resultWriter ch = do 
    f <- obtainFileHandler 
    forever $ do 
     result <- readChan 
     writeToFile f result 

您可能還需要編寫一些邏輯,以便爲resultWriter線程主線程等待完成寫入到磁盤上,但基本上就是這樣。

希望這回答你的問題。

+0

這正是我想要的! – ArchHaskeller

1

你的,你想要做的是有點模糊,所以我很可能會花費更多的信息和更多的問題,你需要什麼來描述。

你的第一個問題:

將TVars能夠處理整數?

有回答 「是」。您可以將任何值存儲在TVar中,但不能取消裝箱值(取消裝箱值是展示某些實現的GHC擴展,並且在該類型中具有#符號)。

有沒有解決方案,我可以拋出f的所有返回值?

我想 「扔」 的意思是 「積少成多」?如果是這樣,那麼你可以在TVarMVar或(如果單線程或非常小心)IOVar可變變量保持運行總數。

注意,存儲 「X + Y」 存儲 「(+)」 施加到 「X」 和 「y」,這是一個懶惰形實轉換。在將其存儲在可變變量中之前,您需要強制添加到弱頭正常形式(WHNF)。

此外,單獨的線程可以讀取它並在同一時間在 緩衝它?

你說的這個問題,「緩衝」是什麼意思?我無法猜測。

如果我保持在多個併發線程訪問的話,我會用一個MVar Integer一個可變變量運行總和。

相關問題