我使用Criterion库为我的Haskell函数编写基准.现在我在C中实现相同的算法来比较Haskell的性能.问题是如何可靠地做到这一点?Criterion做了很多花哨的事情,例如计算时钟调用开销和对结果进行统计分析.我想如果我只是测量我的C函数所需的时间,它将无法与Criterion返回的结果进行比较.在他关于Criterion的原始帖子中, Bryan O'Sullivan写道:"使用标准对C代码和命令行程序进行基准测试应该很容易." 问题是如何?Takayuki Muranushi 比较了DFT的C实现使用Haskell生成线程并调用可执行文件,但我担心这会增加很多额外的开销(创建新线程,运行应用程序,输出到stdio然后从中读取),这使得结果无法比拟.我也考虑使用FFI,但我再次担心额外的开销会使这种比较不公平.
如果没有办法使用Criterion可靠地对C进行基准测试,那么您会推荐哪种C基准测试方法?我在这里读过一些关于SO的问题,似乎有许多不同的函数可以测量系统时间,但是它们要么以毫秒为单位提供时间,要么有大量的调用开销.
我有一段看起来像这样的Haskell代码:
fst . f $ (Z :. i `div` 2)
Run Code Online (Sandbox Code Playgroud)
Z并:.取自Repa库,定义如下:
data Z = Z deriving (Show, Read, Eq, Ord)
infixl 3 :.
data tail :. head = !tail :. !head deriving (Show, Read, Eq, Ord)
Run Code Online (Sandbox Code Playgroud)
表达式右侧$定义了一个数组索引,f而是一个获取该索引并返回一对的函数.这将编译为以下Core:
case f_a2pC
(case ># x_s32E 0 of _ {
False ->
case <# x_s32E 0 of _ {
False -> :. Z (I# (quotInt# x_s32E 2));
True -> :. Z (I# (-# (quotInt# (+# …Run Code Online (Sandbox Code Playgroud) 我使用标准来对我的Haskell代码进行基准测试.我正在做一些繁重的计算,我需要随机数据.我写了这样的主要基准文件:
main :: IO ()
main = newStdGen >>= defaultMain . benchmarks
benchmarks :: RandomGen g => g -> [Benchmark]
benchmarks gen =
[
bgroup "Group"
[
bench "MyFun" $ nf benchFun (dataFun gen)
]
]
Run Code Online (Sandbox Code Playgroud)
我在不同的模块中为它们保留基准和数据生成器:
benchFun :: ([Double], [Double]) -> [Double]
benchFun (ls, sig) = fun ls sig
dataFun :: RandomGen g => g -> ([Double], [Double])
dataFun gen = (take 5 $ randoms gen, take 1024 $ randoms gen)
Run Code Online (Sandbox Code Playgroud)
这有效,但我有两个问题.首先,生成基准中包含的随机数据所需的时间是多少?我发现了一个涉及该主题的问题,但说实话,我无法将其应用于我的代码.为了检查是否发生这种情况,我在IO monad中编写了一个替代版本的数据生成器.我将基准列表与main(称为生成器)放在一起,用< - 提取结果,然后将其传递给基准函数.我发现性能没有差别. …
我想从Haskell运行外部程序并检索其输出和错误流的内容.在其中一个库中我找到了这段代码:
runProcess :: FilePath -> [String] -> IO (ExitCode, String, String)
runProcess prog args = do
(_,o,e,p) <- runInteractiveProcess prog args Nothing Nothing
hSetBuffering o NoBuffering
hSetBuffering e NoBuffering
sout <- hGetContents o
serr <- hGetContents e
ecode <- length sout `seq` waitForProcess p
return (ecode, sout, serr)
Run Code Online (Sandbox Code Playgroud)
这是正确的做法吗?这里有一些我不理解的东西:为什么要设置流NoBuffering?为什么length sout 'seq'?这感觉就像某种黑客.此外,我想将输出和错误流合并为一个,以获得与2>&1在命令行上所做的相同的效果.如果可能,我想避免使用专用的I/O库并依赖GHC提供的标准软件包.
我正在使用英特尔内在函数编写程序.我想使用_mm_permute_pd内在的,仅在具有AVX的CPU上可用.对于没有AVX的CPU我可以使用,_mm_shuffle_pd但根据规格它比它慢得多_mm_permute_pd.英特尔内部函数的头文件是否定义了允许我区分是否支持AVX的常量,以便我可以这样写:
#ifdef __IS_AVX_SUPPORTED__ // is there sth like this defined?
// use _mm_permute_pd
# else
// use _mm_shuffle_pd
#endif
Run Code Online (Sandbox Code Playgroud)
?我找到了这个教程,它展示了如何执行运行时检查,但我需要对当前机器进行静态的编译时检查.
我在Scheme中写过Collatz猜想:
(define C
(lambda (n)
(cond
((eq? n 1) 1)
((even? n) (C (/ n 2)))
(else (C (+ (* n 3) 1))))))
Run Code Online (Sandbox Code Playgroud)
这是一个尾递归调用,但是当我调用时(C 121)我得到堆栈溢出:
guile> (trace C)
(C)
guile> (C 121)
[C 121]
[C 364]
[C 182]
[C 91]
[C 274]
[C 137]
[C 412]
[C 206]
[C 103]
[C 310]
[C 155]
[C 466]
[C 233]
[C 700]
[C 350]
[C 175]
[C 526]
[C 263]
[C 790]
[C 395]
[C 1186]
ERROR: Stack overflow
ABORT: (stack-overflow)
Run Code Online (Sandbox Code Playgroud)
为什么正确的尾递归会导致溢出?如您所见,我使用Guile作为Scheme解释器(版本1.8.7).
我偶然发现了Evalmonad和rpar StrategyHaskell 的问题.考虑以下代码:
module Main where
import Control.Parallel.Strategies
main :: IO ()
main = print . sum . inParallel2 $ [1..10000]
inParallel :: [Double] -> [Double]
inParallel xss = runEval . go $ xss
where
go [] = return []
go (x:xs) = do
x' <- rpar $ x + 1
xs' <- go xs
return (x':xs')
inParallel2 :: [Double] -> [Double]
inParallel2 xss = runEval . go $ xss
where
go [] = return [] …Run Code Online (Sandbox Code Playgroud) 我正在阅读Raymond Smullyan的"嘲笑模仿鸟".在书中有一个谜题是这样的:
这个故事的塞维利亚与西班牙着名的塞维利亚(实际上没有)之间的任何相似之处纯属巧合.在这个神秘的塞维利亚小镇,男性居民戴着假发,只有他们感觉喜欢的那些日子.没有两个居民在所有日子里都表现得一样; 也就是说,如果任何两个男性居民,至少有一天他们中的一个戴着假发而另一个则不戴.鉴于任何男性居民X和Y,居民Y据说是X的追随者,如果在X所有的日子里戴假发.此外,如果居民X,Y和Z,如果Z在X和Y都做的所有日子都佩戴假发,则居民Z被称为X和Y的追随者.
其中五名居民被命名为Alfredo,Bernardo,Ben-ito,Roberto和Ramano.以下事实是关于它们的:
事实1 ......贝尔纳多和贝尼托在他们的假发习惯方面相反; 也就是说,在任何一天,其中一个戴假发,另一个戴假发.
事实2:罗伯托和拉马诺同样是对立的.
事实3:拉马诺戴着假发,只有在阿尔弗雷多和贝尼托都戴上假发的那几天.
塞维利亚只有一个理发师,以下事实是关于他的:
事实4:贝尔纳多是阿尔弗雷多和理发师的追随者.
事实5:鉴于任何男性居民X,如果Bernardo是Alfredo和X的下属,那么理发师就是X的追随者.
阿尔弗雷多只穿黑色假发; 贝尔纳多只穿白色假发; 贝尼托只穿灰色假发; 罗伯托只穿红色假发; 而Ramano只戴着棕色假发.
一个复活节早晨,理发师戴着假发.他穿的是什么颜色?
我发现在Prolog中解决这个问题会很有趣,但我很早就陷入了困境:
isOpposite( bernardo, benito ).
isOpposite( benito , bernardo ).
isOpposite( roberto , ramano ).
isOpposite( ramano , roberto ).
wears( alfredo , black ).
wears( bernardo, white ).
wears( benito , gray ).
wears( roberto , red ).
wears( ramano , brown ).
whatWearsTheBarber( WigColor ) :-
member( Barber, [ alfredo, benito, bernardo, roberto, ramano ] ),
wears( Barber, WigColor …Run Code Online (Sandbox Code Playgroud) 我的目标是foo在比赛分支中包含对某些引理的调用.该调用使用R分支的本地变量作为其参数之一:
| SomeConstr => fun R => .... (foo a b c R) ....
Run Code Online (Sandbox Code Playgroud)
我想执行beta扩展,foo以便调用成为:
| SomeConstr => fun R => .... ((fun d => foo a b c d) R) ....
Run Code Online (Sandbox Code Playgroud)
这将允许我进一步概括(fun d => foo a b c d),这将不会孤独地依赖于分支本地的变量.由于我正在处理非常大的证据,我想用Ltac写这个.这是一个尝试:
match goal with
| [ |- context[(foo ?A ?B ?C ?R)] ] =>
let d := fresh "d" in
replace (foo A B C R) with ((fun d => foo A B …Run Code Online (Sandbox Code Playgroud) 在我的.emacs配置文件中,我有以下条目:
(custom-set-variables
(custom-set-faces
'(font-lock-comment-face ((((class color)
(min-colors 8)
(background dark))
(:foreground "red"))))))
Run Code Online (Sandbox Code Playgroud)
这可以在TERM环境变量设置为时修复字体颜色screen,但在TERM设置为时将其中断xterm.有没有办法阅读的价值TERM变量和执行的代码只有当TERM的值screen?我发现这个questin略有帮助,但我仍然不知道如何在elisp中读取环境变量的值.