- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将一个性能问题作为更复杂代码的一部分进行调试。看来append
我用来创建 (Int,Int,Int,Int)
的动态、可增长向量的函数正在引起 Int
之一在写入向量之前要装箱和拆箱的元组中。我写了一个更简单的代码来重现这个问题——似乎只有当我在 append
中添加向量增长功能时才会发生这种情况。函数 - 下面的示例代码(除了重现问题外,它没有做太多有用的工作),后面是 core
的片段显示装箱和拆箱的值:
{-# LANGUAGE BangPatterns #-}
module Test
where
import Data.Vector.Unboxed.Mutable as MU
import Data.Vector.Unboxed as U hiding (mapM_)
import Control.Monad.ST as ST
import Control.Monad.Primitive (PrimState)
import Control.Monad (when)
import GHC.Float.RealFracMethods (int2Float)
import Data.STRef (newSTRef, writeSTRef, readSTRef)
import Data.Word
type MVI1 s = MVector (PrimState (ST s)) Int
type MVI4 s = MVector (PrimState (ST s)) (Int,Int,Int,Int)
data Snakev s = S {-# UNPACK #-}!Int
!(MVI4 s)
newVI1 :: Int -> Int -> ST s (MVI1 s)
newVI1 n x = do
a <- new n
mapM_ (\i -> MU.unsafeWrite a i x) [0..n-1]
return a
-- Growable array - we always append an element. It grows by factor of 1.5 if more capacity is needed
append :: Snakev s -> (Int,Int,Int,Int) -> ST s (Snakev s)
append (S i v) x = do
if i < MU.length v then MU.unsafeWrite v i x >> return (S (i+1) v)
else MU.unsafeGrow v (floor $! 1.5 * (int2Float $ MU.length v)) >>= (\y -> MU.unsafeWrite y i x >> return (S (i+1) y))
gridWalk :: Vector Word8 -> Vector Word8 -> MVI1 s -> MVI1 s -> Snakev s -> Int -> (Vector Word8 -> Vector Word8 -> Int -> Int -> Int) -> ST s (Snakev s)
gridWalk a b fp snodes snakesv !k cmp = do
let offset = 1+U.length a
xp = offset-k
snodep <- MU.unsafeRead snodes xp -- get the index of previous snake node in snakev array
append snakesv (snodep,xp,xp,xp)
{-#INLINABLE gridWalk #-}
append
用于
gridWalk
.该函数是
$wa
在核心中 - 请注意盒装的 Int 参数:
$wa
:: forall s.
Int#
-> MVI4 s
-> Int#
-> Int#
-> Int#
-> Int ======= Boxed value - one of (Int,Int,Int,Int) is boxed
-> State# s
-> (# State# s, Snakev s #)
$wa =
\ (@ s)
(ww :: Int#)
(ww1 :: MVI4 s)
(ww2 :: Int#)
(ww3 :: Int#)
(ww4 :: Int#)
(ww5 :: Int) === Boxed value
(w :: State# s) ->
....
....
of ipv12 { __DEFAULT ->
case (writeIntArray# ipv7 ww ww4 (ipv12 `cast` ...)) `cast` ...
of ipv13 { __DEFAULT ->
(# case ww5 of _ { I# x# ->
(writeIntArray# ipv10 ww x# (ipv13 `cast` ...)) `cast` ...
},
S (+# ww 1)
((MV_4
(+# y rb)
==== x below unboxed from arg ww5 ======
((MVector 0 x ipv1) `cast` ...)
((MVector 0 x1 ipv4) `cast` ...)
((MVector 0 x2 ipv7) `cast` ...)
((MVector 0 x3 ipv10) `cast` ...))
`cast` ...) #)
gridWalk
调用时将值框起来
append
:
=== function called by gridWalk ======
a :: forall s.
Vector Word8
-> Vector Word8
-> MVI1 s
-> MVI1 s
-> Snakev s
-> Int
-> (Vector Word8 -> Vector Word8 -> Int -> Int -> Int)
-> State# s
-> (# State# s, Snakev s #)
a =
\ (@ s)
(a1 :: Vector Word8)
_
_
(snodes :: MVI1 s)
(snakesv :: Snakev s)
(k :: Int)
_
(eta :: State# s) ->
case k of _ { I# ipv ->
case snodes `cast` ... of _ { MVector rb _ rb2 ->
case a1 `cast` ... of _ { Vector _ rb4 _ ->
let {
y :: Int#
y = -# (+# 1 rb4) ipv } in
case readIntArray# rb2 (+# rb y) (eta `cast` ...)
of _ { (# ipv1, ipv2 #) ->
case snakesv of _ { S ww ww1 ->
====== y boxed below before append called ======
$wa ww ww1 ipv2 y y (I# y) (ipv1 `cast` ...)
}
}
}
}
}
gridWalk
中的值的装箱并在
append
中拆箱在插入
(Int,Int,Int,Int)
的向量之前.标记
append
INLINE
不会改变行为——那些装箱的值只是在
gridWalk
的函数体中移动.
append
的功能(即,在超出容量时处理向量增长)同时重构它。
GHC
版本是
7.6.1
.矢量版是
0.10
.
最佳答案
这只是一个评论。我想我会摆脱元组参数(在 append
中调整 gridWalk
的使用),但结果是(仅)最后一个 Int 参数必须被 bang'd 来取消装箱,这似乎奇怪的:
append :: Snakev s -> Int -> Int -> Int -> Int -> ST s (Snakev s)
append (S i v) a b c !d = do
if i < len then do MU.unsafeWrite v i (a,b,c,d)
return $ S (i+1) v
else do y <- MU.unsafeGrow v additional
MU.unsafeWrite y i (a,b,c,d)
return $ S (i+1) y
where len = MU.length v
additional = floor (1.5 * int2Float len) -- this seems kind of bizarre
-- by the way; can't you stay inside Int?
-- 3 * (len `div` 2) or something
S (i+1)
的应用程序,您可以将所有内容拆箱。在 do 块外面,但我不确定这是否能让我们更接近采石场......:
append :: Snakev s -> Int -> Int -> Int -> Int -> ST s (Snakev s)
append (S i v) a b c d = do
if i < len then liftM (S (i+1)) $ do MU.unsafeWrite v i (a,b,c,d)
return v
else liftM ( S (i+1)) $ do y <- MU.unsafeGrow v zzz
MU.unsafeWrite y i (a,b,c,d)
return y
where len = MU.length v
zzz = floor (1.5 * int2Float len)
liftM
被
fmap
取代我们回到了唯一的未装箱状态。如果
liftM (S (1+i)
一切顺利或
fmap (S (i+1)
一直移到前面:
append (S i v) a b c d = S (i+1) <$> do ...
关于performance - 拆箱四元组向量中的装箱值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16946610/
对于数字密集型代码,我编写了一个具有以下签名的函数: def update( f: (Int,Int,Double) => Double ): Unit = {...} 但是,因为 Function3
鉴于此代码更改: int count = 0; 替换为: int count = NumberUtils.INTEGER_ZERO; 我依靠 Apache NumberUtils 进行更改,只是为了常
我有兴趣在我的解决方案中找到所有发生装箱或拆箱的地方。我知道我可以像这样使用 ildasm: Ildasm.exe yourcomponent.dll /text | findstr box 但我不想
我目前正在努力研究选角和拳击。据我目前了解: 装箱 - 值类型到引用类型(即 int 到对象) 拆箱 - 引用类型到值类型(即对象到 int) Type Casting - 目前在我看来类似于拳击但允
自动装箱/拆箱是编译器还是运行时? 考虑以下示例: public Integer get() { return 1; //(1) } 在 (1) 处,原始整数值将被转换为类似于 new In
试图说服某人从 .NET 1.1 切换 我看到有人说在 .NET 1.1 之后使用 Dictionary 类的一个优点是性能提高,因为不必拆箱/转换对象。除此之外还有其他改进吗? 或者离开 .NET
大家可以向我解释一下 new 的性质以及 Integer 的使用 Integer i = new Integer(-10); Integer j = new Integer(-10); Integer
public IList A23 { get; set; } s.A23 = new List(new int[] { 62, 63, 64 }); IList g = s.A23; double d
如果我有一个包含 Object 的列表,如下所示: List t = new List(); t.Add(10); t.Add("xyx"); 在这种情况下,如果我取回列表项,是否需要将它们拆箱? 最
最近在学习值类型,有点迷茫。此外,转换和拆箱都使用相同的语法 - (expected type)(object),对吧?那么类型之间的简单转换呢,即强制转换或只是转换? int x = (int)2.
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在使用 NSJSONSerialization 将 JSON 文档转换为 Core Foundation 类型。 我的 JSON 中有一个字段,它是一个“数字”。它有时是整数,有时是 float
我已阅读 this excellent question关于如何定期int[]在 foreach 下处理(框与否)循环。 Array确实实现了非泛型 IEnumerable所以它必须使用 object
在对 this question 的公认最佳回复中,有一个明确的解释为什么拳击会发生。 但是,如果我反编译代码(使用 java 反编译器),我看不到 scala.runtime.BoxesRunTim
根据最近的即席建议,关于如何让 Scala 通过查看字节码告诉我是否正在进行拳击,我创建了这个类: class X { def foo(ls : Array[Long]) = ls map (_.to
在一些代码中我看到了这个: private void compute(Long a, Long b, Long c) { long result = a-(b+c); ... 结果存储
我的 Sonar 6.7.1 LTS 实例无法识别以下代码中的 NullPointerException: public static boolean getBooleanFromMap() {
我发现 float 和 double 在不同情况下有后缀。那么 float 的后缀 F 和 f, double 的后缀 D 和 d 有什么区别?有这种行为的历史吗? 还有关于类型构造函数的问题,例如
我很想知道 C# 中的所有强制转换是否都会导致装箱,如果不是,所有强制转换都是代价高昂的操作吗? 示例取自 Boxing and Unboxing (C# Programming Guide)
这个问题在这里已经有了答案: 关闭 9 年前。 Possible Duplicate: Structs, Interfaces and Boxing 来自 MSDN:http://msdn.micr
我是一名优秀的程序员,十分优秀!