15

我使用 Criterion 库为我的 Haskell 函数编写基准测试。现在我在 C 中实现相同的算法来比较 Haskell 的性能。问题是我怎样才能可靠地做到这一点?Criterion 做了很多花哨的事情,比如计算时钟调用开销和对结果进行统计分析。我想如果我只是测量我的 C 函数所需的时间,它将无法与 Criterion 返回的结果相提并论。在他关于 Criterion 的原始帖子中, Bryan O'Sullivan 写道:“甚至应该很容易使用标准来对 C 代码和命令行程序进行基准测试。” 问题是如何?Takayuki Muranushi比较 DFT 的 C 实现使用 Haskell 通过生成线程并调用可执行文件,但我担心这会增加很多额外的开销(创建新线程,运行应用程序,输出到 stdio,然后从中读取),这使得结果无法比较。我也考虑过使用 FFI,但我再次担心额外的开销会使这种比较不公平。

如果无法使用 Criterion 可靠地对 C 进行基准测试,那么您会推荐哪些 C 基准测试方法?我在这里阅读了一些关于 SO 的问题,似乎有许多不同的函数可以测量系统时间,但它们要么以毫秒为单位提供时间,要么具有很大的调用开销。

4

1 回答 1

13

FFI 可以以不会增加太多开销的方式使用。考虑以下程序(此处提供完整代码):

foreign import ccall unsafe "mean" c_mean :: Ptr CInt -> CUInt -> IO CFloat

main :: IO ()
main = do
  buf <- mallocBytes (bufSize * sizeOfCInt)
  fillBuffer buf 0
  m <- c_mean buf (fromIntegral bufSize)
  print $ realToFrac m

C 调用编译为以下 Cmm:

s2ni_ret() { ... }
    c2qy:
        Hp = Hp + 12;
        if (Hp > I32[BaseReg + 92]) goto c2qC;
        _c2qD::I32 = I32[Sp + 4];
        (_s2m3::F32,) = foreign "ccall"
          mean((_c2qD::I32, PtrHint), (100,));

这是组装:

s2ni_info:
.Lc2qy:
        addl $12,%edi
        cmpl 92(%ebx),%edi
        ja .Lc2qC
        movl 4(%ebp),%eax
        subl $4,%esp
        pushl $100
        pushl %eax
        ffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)
        ffree %st(4) ;ffree %st(5)
        call mean

因此,如果您将 C 导入标记为unsafe并在测量之前进行所有编组,那么您的 C 调用基本上只是一个内联call指令 - 就像您在 C 中进行所有基准测试一样。这是我对 C 函数进行基准测试时 Criterion 报告的内容什么也没做:

benchmarking c_nothing
mean: 13.99036 ns, lb 13.65144 ns, ub 14.62640 ns, ci 0.950
std dev: 2.306218 ns, lb 1.406215 ns, ub 3.541156 ns, ci 0.950
found 10 outliers among 100 samples (10.0%)
  9 (9.0%) high severe
variance introduced by outliers: 91.513%
variance is severely inflated by outliers

这大约比我机器上估计的时钟分辨率小 400 倍(约 5.5 微秒)。为了比较,这里是计算 100 个整数的算术平均值的函数的基准数据:

benchmarking c_mean
mean: 184.1270 ns, lb 183.5749 ns, ub 185.0947 ns, ci 0.950
std dev: 3.651747 ns, lb 2.430552 ns, ub 5.885120 ns, ci 0.950
found 6 outliers among 100 samples (6.0%)
  5 (5.0%) high severe
variance introduced by outliers: 12.329%
variance is moderately inflated by outliers
于 2012-10-22T14:02:03.477 回答