我一直在检查integer-gmp源代码,以了解如何根据GHC Primops页面上记录的cmm实现外部primops .我知道使用llvm hack或fvia-C/gcc 实现它们的技术- 这对我来说是理解interger-gmp库使用的第三种方法的更多学习经验.
所以,我抬头一看CMM教程MSFT页(PDF链接),经历了GHC CMM页,仍然存在一些悬而未决的问题(很难保持在头所有这些概念没有挖掘到CMM这就是我现在所做的).这是来自integer-bmp cmm文件的代码片段:
integer_cmm_int2Integerzh (W_ val)
{
W_ s, p; /* to avoid aliasing */
ALLOC_PRIM_N (SIZEOF_StgArrWords + WDS(1), integer_cmm_int2Integerzh, val);
p = Hp - SIZEOF_StgArrWords;
SET_HDR(p, stg_ARR_WORDS_info, CCCS);
StgArrWords_bytes(p) = SIZEOF_W;
/* mpz_set_si is inlined here, makes things simpler */
if (%lt(val,0)) {
s = -1;
Hp(0) = -val;
} else {
if (%gt(val,0)) {
s = 1;
Hp(0) = val; …Run Code Online (Sandbox Code Playgroud) go worker tail-recursive loop pattern似乎非常适合编写纯代码.为STmonad 编写这种循环的等效方法是什么?更具体地说,我想避免循环迭代中的新堆分配.我的猜测是它涉及任一CPS transformation或fixST重新写使得所有在跨越环路改变的值被在每个迭代中通过,从而使寄存器的位置(或在溢出的情况下,叠加)适用于在可迭代这些值的代码.我在下面有一个简化的示例(不要尝试运行它 - 它可能会因为分段错误而崩溃!),其中涉及一个findSnakes具有go工作模式的函数,但更改的状态值不通过累加器参数传递:
{-# 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 as CM (when,forM_)
import Data.Int
type MVI1 s = MVector (PrimState (ST s)) Int
-- function to find previous y
findYP :: MVI1 s -> Int -> Int -> ST s Int
findYP fp …Run Code Online (Sandbox Code Playgroud) 由于a ByteString是一个构造函数ForeignPtr:
data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
{-# UNPACK #-} !Int -- offset
{-# UNPACK #-} !Int -- length
Run Code Online (Sandbox Code Playgroud)
如果我有一个返回的函数ByteString,那么给定一个输入,比如一个常量Word8,该函数将返回一个具有非确定性ForeignPtr值的ByteString - 该值将由内存管理器确定.
那么,这是否意味着返回ByteString的函数不纯?如果您使用了ByteString和Vector库,那么这似乎并非如此.当然,如果是这样的话,它将被广泛讨论(并希望在谷歌搜索之上显示).这种纯度是如何实施的?
提出这个问题的原因是我很好奇从GHC编译器的角度来看,使用ByteString和Vector对象有什么微妙之处,在构造函数中给出了ForeignPtr成员.
我有一个非递归函数来计算似乎表现良好的最长公共子序列(ghc 7.6.1用-O2 -fllvm标志编译),如果我Criterion在同一模块中测量它.在另一方面,如果我转换功能为模块,只导出功能(如建议在这里),然后用标准重新测量,我得到〜2倍放缓(这会消失,如果我移动的标准测回模块其中定义了函数).我尝试用INLINEpragma 标记函数,这对跨模块性能测量没有任何影响.
在我看来,GHC可能正在进行严格性分析,当函数和main(函数可以从中访问)位于同一模块中时,它可以很好地工作,但是当它们被分割时则不行.我希望有关如何模块化函数的指针,以便在从其他模块调用时表现良好.有问题的代码太大了,无法在此处粘贴 - 如果您想尝试一下,可以在此处查看.我正在尝试做的一个小例子如下(使用代码片段):
-- Function to find longest common subsequence given unboxed vectors a and b
-- It returns indices of LCS in a and b
lcs :: (U.Unbox a, Eq a) => Vector a -> Vector a -> (Vector Int,Vector Int)
lcs a b | (U.length a > U.length b) = lcsh b a True
| otherwise = lcsh a b False
-- …Run Code Online (Sandbox Code Playgroud) 我正在使用向量库和状态monad在Haskell中编写一个最长的公共子序列算法(以封装Miller O(NP)算法的非常强制性和可变性).我已经用C语言编写了一些我需要它的项目,现在我正在用Haskell编写它作为一种探索如何编写具有匹配C的良好性能的命令式网格遍历算法的方法.我用unboxed向量编写的版本对于相同的输入,它比C版本慢大约4倍(并且使用正确的优化标志编译 - 我同时使用了系统时钟和Criterion验证Haskell和C版本之间相对时间测量的方法,以及相同的数据类型,包括大输入和小输入).我一直试图弄清楚性能问题可能在哪里,并会欣赏反馈 - 有可能在这里遇到一些众所周知的性能问题,特别是在我在这里大量使用的矢量库中.
在我的代码中,我有一个名为gridWalk的函数,它最常被调用,并且还完成了大部分工作.性能下降很可能会出现,但我无法弄清楚它可能是什么.完整的Haskell代码就在这里.以下代码的片段:
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 Data.STRef (newSTRef, modifySTRef, readSTRef)
import Data.Int
type MVI1 s = MVector (PrimState (ST s)) Int
cmp :: U.Vector Int32 -> U.Vector Int32 -> Int -> Int -> Int
cmp a b i j = go 0 i j
where
n = U.length a
m = U.length …Run Code Online (Sandbox Code Playgroud) 是否可以使用ghcjs?将Haskell模块编译为JS ?我玩它,但它似乎需要main在生成JS之前定义函数.下面的玩具代码:
module Test where
add :: Int -> Int -> Int
add x y = x + y
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何使用它将其编译为JS ghcjs.如果未定义main函数,它将仅编译.hi和.o文件.如果我能想出办法来把它编译成JS(在适当的Z-encoded功能名称,以及相应的JS对象,像我们在FFI为C),然后我可以使用更强大的Haskell库,例如unordered-containers和vector实现一些算法,编译成JS,并Elm通过JS FFI使用.
Fay似乎有能力做到这一点.我想首先调查一下ghcjs.
MVar在C中是否有任何已知的Haskell实现?有一个关于如何在C++中实现它的例子.但是,我想在C中实现它 - 让我们现在只说MVar CIntC中的等价物.编写同步原语可能很棘手.所以,如果有人已经做过,我希望避免重复劳动.我完全不理解上面的C++示例,可以自信地将其转换为C语言 - 它从我的C++中很好地隐藏了算法细节 - 缺乏经验的头脑:)
我想在C中编写MVar的原因是因为它使我很容易使用FFI绑定到外部C库来获取数据流,并使用Haskell线程来获取数据(来自Storable向量以避免编组数据 - MVar CInt在这里存储了多少可存储的向量.我需要确保在Haskell线程读取数据时阻塞写入Storable位置的C线程.这就是C侧的MVar同步有帮助的地方.从Haskell调用不安全甚至安全的C函数(在我的测试中安全性约为15ns,在测试中安全性约为150ns)比从C调用Haskell(~5us)要快得多.如果回调很快,我会将C函数回调到Haskell,并在Haskell MVar上阻塞.
更新:
伪代码中的算法也可以.考虑到newEmptyMVar,takeMVar和putMVar的算法,在C中实现它应该很容易.
我正在尝试Yesod在Yesod网页上记录的书籍示例.其中一个示例是Wiki中嵌入的聊天应用程序.当我在ghci(加载Chat模块,Wiki.hs其中包含Wiki示例代码)中尝试它时,我得到以下关于Chat.hs的错误:
Chat.hs:122:34:
Could not deduce (Text.Julius.ToJavascript Text)
arising from a use of `Text.Julius.toJavascript'
from the context (YesodChat master)
bound by the type signature for
chatWidget :: YesodChat master =>
(Route Chat -> Route master) -> GWidget sub master ()
at Chat.hs:(81,15)-(83,35)
Possible fix:
add an instance declaration for (Text.Julius.ToJavascript Text)
In the first argument of `Text.Julius.Javascript', namely
`Text.Julius.toJavascript output'
In the expression:
Text.Julius.Javascript (Text.Julius.toJavascript output)
In the first argument of `Data.Monoid.mconcat', namely …Run Code Online (Sandbox Code Playgroud) 我试图使用Haskell Iteratee库提出相当于"wc -l"的东西.下面是"wc"的代码(它只计算单词 - 类似于hackage上的iteratee示例中的代码),并且运行速度非常快:
{-# LANGUAGE BangPatterns #-}
import Data.Iteratee as I
import Data.ListLike as LL
import Data.Iteratee.IO
import Data.ByteString
length1 :: (Monad m, Num a, LL.ListLike s el) => Iteratee s m a
length1 = liftI (step 0)
where
step !i (Chunk xs) = liftI (step $ i + fromIntegral (LL.length xs))
step !i stream = idone i stream
{-# INLINE length1 #-}
main = do
i' <- enumFile 1024 "/usr/share/dict/words" (length1 :: (Monad m) => Iteratee ByteString …Run Code Online (Sandbox Code Playgroud) 最近,我读了纸张在即将到来的广义流的融合vector和DPH图书馆.这似乎是非常有趣的发展.我现在开始尝试DPH(从GHC 7.6开始,并计划在它出来时升级到7.8 SIMD版本).我还从Repa库文档中看到它可以执行并行数组工作.Repa似乎是成熟的版本,相比之下DPH,GHC 7.4没有被认为是准备好的.现在,DPH似乎是成熟的,我想知道什么是之间的主要优点和缺点Repa和DPH封装,GHC 7.6.我搜索了StackOverflow和谷歌,但找不到Repa和之间的比较DPH.因此,这个问题.