- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在做基准测试 forkIO
使用以下代码:
import System.Time.Extra
import Control.Concurrent
import Control.Monad
import Data.IORef
n = 200000
main :: IO ()
main = do
bar <- newEmptyMVar
count <- newIORef (0 :: Int)
(d, _) <- duration $ do
replicateM_ n $ do
forkIO $ do
v <- atomicModifyIORef' count $ \old -> (old + 1, old + 1)
when (v == n) $ putMVar bar ()
takeMVar bar
putStrLn $ showDuration d
IORef
运行,当它们都开始时,完成。在 Windows 上使用命令
ghc --make -O2 Main -threaded && main +RTS -N4
在 GHC 8.10.1 上运行时性能差异很大。有时需要 > 1 秒(例如 1.19 秒),有时需要 < 0.1 秒(例如 0.08 秒)。似乎它大约有 1/6 的时间在更快的桶中。为什么性能差异?是什么导致它跑得更快?
n
高达 1M 效果消失,它始终在 5+s 范围内。
最佳答案
我也可以在 Ubuntu 上确认相同的行为。除非我设置 n=1M
这种行为不会消失,我的运行时间范围为 2 到 7 秒。
我相信调度程序的不确定性是导致运行时出现如此显着差异的原因。当然,这不是一个确定的答案,因为这只是我的猜测。atomicModifyIORef'
使用 CAS(比较和交换)实现,因此取决于线程的执行方式 old + 1
将或多或少地重新计算。换句话说,如果线程 B 更新 count
ref 在线程 A 有机会更新 count
之前ref,但是在它开始更新之后,它必须从头开始更新操作,因此从 ref 中读取新的更新值并重新计算 old + 1
再次。
如果你运行 main +RTS -N1
,您会看到不仅运行程序所需的时间要少得多,而且执行之间的运行时间也非常一致。我怀疑这是因为任何时候只能运行一个线程,并且在 atomicModifyIORef'
之前没有抢占。已经完成了。
希望其他对 Haskell RTS 有深入了解的人可以对这种行为提供更多的见解,但这是我的看法。
编辑
@NeilMitchel 评论道:
I'm not convinced it's anything to do with the atomic modification at all
PVar
的实现。这依赖于
casIntArray#
下。它不仅快 10 倍,而且没有观察到差异:
import System.Time.Extra
import Control.Concurrent
import Control.Monad
import Data.Primitive.PVar -- from `pvar` package
n = 1000000
main :: IO ()
main = do
bar <- newEmptyMVar
count <- newPVar (0 :: Int)
(d, _) <- duration $ do
replicateM_ n $ do
forkIO $ do
v <- atomicModifyIntPVar count $ \old -> (old + 1, old + 1)
when (v == n) $ putMVar bar ()
takeMVar bar
putStrLn $ showDuration d
关于performance - GHC forkIO 双峰性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61971292/
我试图以此为例,但似乎无法使其适应我的数据集,因为我需要截断的法线: https://stackoverflow.com/questions/35990467/fit-two-gaussians-to
我是一名优秀的程序员,十分优秀!