- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我为一个编程问题提交的两份报告仅在一个表达式上有所不同(其中 anchors
是一个非空列表,(getIntegrals n)
是一个状态单子(monad)):
Submission 1 . replicateM (length anchors - 1) (getIntegrals n)
Submission 2 . sequenceA $ const (getIntegrals n) <$> tail anchors
我猜这两个表达式的等价性在编译时应该很容易看出。然而,comparatively sequenceA
一个更慢,更重要的是,占用 >10 倍的内存:
代码
时间
内存
复制M一
732 毫秒
22200 KB
序列一个
1435 毫秒
262100 KB
(第二个条目出现“测试 4 超出内存限制”错误,因此情况可能更糟)。
为什么会这样?
很难预测哪些优化是自动的,哪些不是!
编辑:按照建议,粘贴 Submission 1下面的代码。在这个交互式问题中,“服务器”有一个大小为 n
的隐藏树。 .我们的代码的工作是找出那棵树,使用最少量的 ? k
形式的查询。 .粗略地说,服务器对 ? k
的响应是节点 k
对应的行在树的邻接距离矩阵中。我们的选择k
是:最初 1
,然后从 getAnchors
获得一堆节点.
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -O2 #-}
import Data.Maybe
import qualified Data.ByteString.Lazy.Char8 as B8
import qualified Data.ByteString.Builder as Bu
import Data.Functor.Identity
import Control.Monad.Trans.State
import Control.Monad
import Control.Applicative
import Data.ByteString.Builder.Extra (flush)
import System.IO
type St = StateT [B8.ByteString] Identity
solve :: St Bu.Builder
solve = do
n <- getIntegral
ds <- getIntegrals n -- get the first row of adjacency matrix
let
anchors = getAnchors ds
readFirst = if head anchors==1 then return ds else getIntegrals n
readRest = replicateM (length anchors - 1) (getIntegrals n) -- get some other rows too
adjss <- liftA2 (:) readFirst readRest
let
adj1ss = [map snd $ filter ((1==).fst) (zip adjs [1..]) | adjs <- adjss]
s0 = Bu.string7
snl = Bu.string7 "\n" <> flush
i0 = Bu.intDec
printEdge src dst = i0 src <> s0 " " <> i0 dst <> snl
printAdj (src,dsts) = mconcat [printEdge src dst | dst<-dsts]
printAdjs = mconcat $ printAdj <$> zip anchors adj1ss
ask k = s0 "? " <> i0 k <> snl
askRest = mconcat $ ask <$> (dropWhile (==1) anchors)
return $ ask 1 <> askRest <> s0 "!" <> snl <> printAdjs
getAnchors :: [Int]->[Int]
getAnchors xs = reverse $ go (zip xs [1..]) [] [] where
go [] odds evens = if length odds < length evens then odds else evens
go ((k,i):rest) odds evens
| even k = go rest odds (i: evens)
| odd k = go rest (i: odds) evens
getByteString :: St B8.ByteString
getByteString = state getNext where
getNext [] = (B8.take 0 (B8.pack "."),[])
getNext (w:ws) = (w,ws)
getIntegral :: Num t => St t
getIntegral = convertToNum <$> getByteString where
convertToNum x = fromIntegral $ fromMaybe 0 $ liftA fst $ B8.readInteger x
getIntegrals :: Num t => Int -> St [t]
getIntegrals n = replicateM n getIntegral
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
bytestrings <- B8.words <$> B8.getContents
B8.putStr $ Bu.toLazyByteString $ evalState solve bytestrings
最佳答案
这里的问题与内联有关。我不完全理解它,但这是我理解的。
内联
首先我们发现复制粘贴definition of replicateM
进入提交 1 会产生与提交 2 (submission) 相同的糟糕性能。但是,如果我们替换 INLINABLE
replicateM
的编译指示与 NOINLINE
pragma 事情再次起作用( submission )。INLINABLE
编译指示 replicateM
不同于 INLINE
pragma,后者导致比前者更多的内联。具体来说,如果我们定义 replicateM
在同一个文件中,用于内联的 Haskells 启发式决定内联,但使用 replicateM
在这种情况下,即使存在 INLINABLE
,它也从基础决定反对内联。语用。sequenceA
和 traverse
另一方面,两者都有 INLINE
导致内联的编译指示。从上述实验中得到提示,我们可以定义一个不可内联的 sequenceA
并且这确实使解决方案 2 起作用( submission )。
{-# NOINLINE sequenceA' #-}
sequenceA' :: [St x] -> St [x]
sequenceA' = sequenceA
出了什么问题?
readRest = replicateM (length anchors - 1) (getIntegrals n)
现在有趣的是,在内联代码中,黄色突出显示的行在
replicateM
的每个循环中运行。 ,而在非内联部分,它们只计算一次,在传递给
replicateM
的 lambda 抽象之外。 .
ds
在核心,但这个是指这个:
solve = do
n <- getIntegral
所以我认为正在发生的是,而不是运行
getIntegral
一次并保存结果,它的起始状态被保存,并且在循环的每一次通过时都以该状态重新运行。确实将此行更改为以下内容(需要 BangPatterns 语言扩展)修复了所有版本(
submission )。
solve = do
!n <- getIntegral
我仍然不确定,但这是我最好的猜测。
getContents
并懒惰地强制它,同时确保在强制太多之前提供输出。相反,明确地逐行读取输入会更安全。 IE。替换
StateT [ByteString]
与
IO
或者更花哨的东西,比如
Conduit
或
Pipe
.
关于performance - 为什么 replicateM (length xs) m 比 sequenceA (fmap (const m) xs) 更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69883964/
我遇到了一个奇怪的问题。我有这个: $(document).ready(function () {
我正在编写一个程序,它从列表中读取一些 ID,从中找出不同的 URL,然后将图像保存到我的 C: 驱动器中。 如果我在浏览器中导航到图像 URL,它们就会起作用。此外,如果我尝试从不同的服务器获取图像
我编写了一个 REST WCF RIA Silverlight 4.0 兼容服务,我可以从 javascript + jQuery.1.4.2.js + JSON2.js(当然,还可以从 .NET 4
我很确定这个网站实际上还没有得到回答。一劳永逸地,与 32 位有符号整数范围内的数字字符串匹配的最小正则表达式是什么,范围是 -2147483648至 2147483647 . 我必须使用正则表达式进
我有两个data.table;我想从那些与键匹配的元素中随机分配一个元素。我现在这样做的方式相当慢。 让我们具体点;这是一些示例数据: dt1<-data.table(id=sample(letter
我已经安装了 celery 、RabitMQ 和花。我可以浏览到花港。我有以下简单的工作人员,我可以将其附加到 celery 并从 python 程序调用: # -*- coding: utf-8 -
我正在使用 ScalaCheck 在 ScalaTest 中进行一些基于属性的测试。假设我想测试一个函数,f(x: Double): Double仅针对 x >= 0.0 定义的, 并返回 NaN对于
我想检查文件是否具有有效的 IMAGE_DOS_SIGNATURE (MZ) function isMZ(FileName : String) : boolean; var Signature: W
在 Herbert Schildt 的“Java:完整引用,第 9 版”中,有一个让我有点困惑的例子。它的关键点我无法理解可以概括为以下代码: class Test { public stat
我在工作中查看了一些代码,发现了一些我以前没有遇到过的东西: for (; ;) { // Some code here break; } 我们一直调用包含这个的函数,我最近才进去看看它是
在 Herbert Schildt 的“Java:完整引用,第 9 版”中,有一个让我有点困惑的例子。它的关键点我无法理解可以概括为以下代码: class Test { public stat
我试图编写一个函数,获取 2D 点矩阵和概率 p 并以概率 p 更改或交换每个点坐标 所以我问了一个question我试图使用二进制序列作为特定矩阵 swap_matrix=[[0,1],[1,0]]
这个问题在这里已经有了答案: Using / or \\ for folder paths in C# (5 个答案) 关闭 7 年前。 我在某个Class1中有这个功能: public v
PostgreSQL 10.4 我有一张 table : Column | Type ------------------------- id | integer| title
我正在 Postgresql 中编写一个函数,它将返回一些针对特定时区(输入)计算的指标。 示例结果: 主要问题是这只是一个指标。我需要从其他表中获取其他 9 个指标。 对于实现此目标的更简洁的方法有
我需要在 python 中模拟超几何分布(用于不替换采样元素的花哨词)。 设置:有一个装满人口许多弹珠的袋子。弹珠有两种类型,红色和绿色(在以下实现中,弹珠表示为 True 和 False)。从袋子中
我正在使用 MaterializeCSS 框架并动态填充文本输入。我遇到的一个问题是,在我关注该字段之前,valid 和 invalid css 类不会添加到我的字段中。 即使我调用 M.update
是否有重叠 2 个 div 的有效方法。 我有以下内容,但无法让它们重叠。 #top-border{width:100%; height:60px; background:url(image.jpg)
我希望你们中的一位能向我解释为什么编译器要求我在编译单元中重新定义一个静态固定长度数组,尽管我已经在头文件中这样做了。这是一个例子: 我的类.h: #ifndef MYCLASS_H #define
我正在使用旧线程发布试图解决相同问题的新代码。什么是安全 pickle ? this? socks .py from socket import socket from socket import A
我是一名优秀的程序员,十分优秀!