Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 比顺序的性能更差_Haskell_Concurrency - Fatal编程技术网

Haskell 比顺序的性能更差

Haskell 比顺序的性能更差,haskell,concurrency,Haskell,Concurrency,我编写了一个函数,通过过滤器将文件从48kHz向上采样到192kHz: upsample :: Coefficients -> FilePath -> IO () 它获取过滤器系数、文件路径(必须为上采样)并将结果写入新文件 我必须对许多文件进行上采样,因此我编写了一个函数,使用Control.Concurrent.Async中的forconcurrent\ucode>对完整目录进行并行上采样: upsampleDirectory :: Directory -> FilePa

我编写了一个函数,通过过滤器将文件从48kHz向上采样到192kHz:

upsample :: Coefficients -> FilePath -> IO ()
它获取过滤器系数、文件路径(必须为上采样)并将结果写入新文件

我必须对许多文件进行上采样,因此我编写了一个函数,使用
Control.Concurrent.Async
中的
forconcurrent\ucode>对完整目录进行并行上采样:

upsampleDirectory :: Directory -> FilePath -> IO ()
upsampleDirectory dir coefPath = do
  files <- getAllFilesFromDirectory dir
  coefs <- loadCoefficients coefPath
  forConcurrently_ files $ upsample coefs
upsampleDirectory::Directory->FilePath->IO()
upsampleDirectory目录coefPath=do

文件这里有几种可能性。首先,确保自己100%地使用
+RTS-N2-RTS
运行程序。我无法告诉您我已经对并行程序进行了多少次基准测试,并编写了:

stack exec myprogram +RTS -N2 -RTS
代替:

stack exec myprogram -- +RTS -N2 -RTS
让自己陷入绝望的困惑。(第一个版本在两个处理器上运行堆栈可执行文件,但目标可执行文件在一个处理器上运行!)可以在
main
程序的开头添加
print$getNumCapabilities

在确认您在两个处理器上运行之后,下一个最可能的问题是您的实现没有在恒定空间中运行,并且正在破坏堆。这里有一个简单的测试程序,我用来尝试复制你的问题。(您可以随意使用我的很棒的上采样过滤器!)

它在单个文件上运行3.7秒,在单个处理器上运行两个副本时运行7.8秒,在使用
+RTS-N2
的两个处理器上运行两个副本时运行4.0秒

确保编译时启用了优化,对程序进行概要分析,并确保它在恒定(或至少合理)堆空间中运行。上述程序在一个恒定的100k字节堆中运行。类似的版本使用严格的
ByteString
进行读取,使用惰性的
ByteString
进行写入,将整个文件读取到内存中,但堆几乎在几分之一秒内立即增长到70meg(文件大小),然后在处理文件时保持不变


无论您的过滤器有多复杂,如果您的程序正在增加千兆字节的堆,那么实现就会中断,在您担心性能、并行性或其他问题之前,您需要修复它。

您的代码中是否存在大量磁盘活动?我希望并行写入两个文件的速度比顺序写入慢,至少对于每个非顺序访问都需要查找时间的HDD而言。@chi every
upsample
call将文件内容读取到内存中,并将结果写入新文件。文件大小为12MB。如果这是大部分CPU时间,看起来确实很奇怪。你能确认两个处理器都使用了一些CPU监视器吗?@chi顺序访问比随机访问快很多数量级,即使是固态磁盘。事实上,与随机存取相比,顺序存取对于RAM来说大约快一个数量级。有趣的是,硬盘的顺序存取(非固态)比固态顺序存取(以很小的比例)要快,与RAM的随机存取相比(!)大约在2009年,但我想总体状况并没有太大变化。
module Main where

import Control.Concurrent.Async
import System.Environment
import qualified Data.ByteString as B

upsample :: FilePath -> IO ()
upsample fp = do c <- B.readFile fp
                 let c' = B.pack $ concatMap (replicate 4) $ B.unpack c
                 B.writeFile (fp ++ ".out") c'

upsampleFiles :: [FilePath] -> IO ()
upsampleFiles files = do
  forConcurrently_ files $ upsample

main :: IO ()
main = upsampleFiles =<< getArgs   -- sample all file on command line
import qualified Data.ByteString.Lazy as B