2017-05-25 33 views
2

我正在編寫一個程序,對文件中的示例數據執行轉換。我通過讀取文件來完成這一操作,將內容轉換爲矢量,對矢量執行轉換,然後將矢量寫回文件。我已經(想)我有一種有效的方式來閱讀文件,並將其內容轉換爲矢量,但我仍然在尋找一種有效的方法將結果向量寫回內存。高效地將矢量轉換並寫入句柄

該文件中的示例是24位整數(3個字節),我通過規範化它們以將它們轉換爲浮點數。

我通過ByteString.hGet讀取所有樣本,將文件內容轉換爲向量。然後,我可以簡單地使用Vector.generateByteString的每3個字節轉換爲一個樣本。

我的問題是將結果寫回文件。至少我覺得有一個問題。我目前的轉化載體,並寫入文件,如下所示:通過

import Data.Vector.Unboxed as U 
import Data.ByteString as BS 

putSamples :: Handle -> U.Vector Float -> IO() 
putSamples h vec = U.forM_ vec (BS.hPut h . BS.pack . unconvert 3 . Int) 

正如你所看到的,我第一次被轉換Float回到一個Int去正常化它,打開Int到3個字節將unconvert 3,pack的結果轉換成的3字節,然後通過ByteString.pack將結果寫入ByteString.hPut的句柄。

這似乎非常低效,因爲我打電話給每個樣品hPut。有沒有辦法更有效地做到這一點?

+0

我可能會換'U.Vector Float'在'newtype'並創建'Data.Serialize.Serialize'一個實例。我相信這將有效地構建一個緩衝區,然後可以在一個操作中寫入。 – ryachza

回答

1

實例殼體創建Serialize實例:

import qualified Data.Vector.Unboxed as U 
import qualified Data.Serialize as S 

newtype MyVec = MyVec (U.Vector Float) 

instance S.Serialize MyVec where 
    put (MyVec vec) = 
    U.forM_ vec $ \_ -> 
     let word1 = 0; word2 = 0; word3 = 0 
     in do 
     S.putWord8 word1 
     S.putWord8 word2 
     S.putWord8 word3 
    get = error "MyVec::S.Serialize: not implemented" 

test = S.encode $ MyVec $ U.singleton 0 
+0

這似乎比我原來的實現更快。但是,它似乎消耗更多的內存。我需要在文件目錄上運行這個。我無法在19個文件的目錄上運行它,因爲它吞噬了內存。它使用我以前的實現工作。無論如何,感謝您的輸入! –

+0

@ThomasVanhelden我希望看到你的實現,也許作爲一個關於兩者之間的區別的新問題?我不確定序列化方法如何影響內存消耗。你的每個文件可以單獨處理,還是必須保持一些狀態?如果前者,我肯定會確保在文件處理完成後沒有引用。 – ryachza