2009-12-29 39 views
4

我正在读的博文在: http://flyingfrogblog.blogspot.com/2009/07/ocaml-vs-f-burrows-wheeler.html使函数内联避免关闭?

的陋居惠勒压缩算法的简单实现:

# compare two strings str[i..end,0..i-1] and str[j..end,0..j-1] 
let cmp (str: _ array) i j = 
    let rec cmp i j = 
    if i=str.Length then 1 else 
     if j=str.Length then -1 else 
     let c = compare str.[i] str.[j] in 
     if c<>0 then c else 
      cmp (i+1) (j+1) 
    cmp i j 
# sort n strings 
let bwt (str: byte array) = 
    let n = str.Length 
    let a = Array.init n (fun i -> i) 
    Array.sortInPlaceWith (cmp str) a 
    Array.init n (fun i -> str.[(a.[i] + n - 1) % n]) 

这个实现似乎很有效,但实际上慢,因为排序Array.sortInPlaceWith (cmp str) a采用了闭合功能(cmp str),并称它太多次(平均O(n log n))!

通过内联排序算法和比较函数,内联速度很快。

我的问题是,内联函数是否意味着seeming-closure调用不再是闭包?

另一件事我想是在C函数指针当我们使用快速排序:

void qsort (void * base, size_t num, size_t size, int (* comparator) (const void *, const void *)); 

我们需要一个比较函数的指针传递。看来在C的情况下,速度并没有太大的吸引力。

谢谢!

回答

6

我们需要传递一个比较函数的指针。在C的情况下似乎是 ,速度并没有太大的吸引力。

它的确如果你将它与一个C++实现std::sort比较。

您可以将C++版本视为上面提到的内联代码。通过使用模板,您不需要运行时间间接来调用函数指针,但编译器可以直接在编译时间处插入和优化给定的比较谓词。

在上面的F#代码中,第一个实现将要求编译器生成一个在运行时通过间接调用的闭包对象,而内联版本不需要间接寻址,因为它的实现在编译时已知。 (但是由于.NET的JIT编译器甚至可以在运行时做这样的优化,所以我从来没有想过这种差异会很大)

+0

谢谢。我有很多qsort和std :: sort的经验。排序更快,但只有一点点。 Jon Harrop说他的内联版本快了100倍。也许这是F#编译器的旧版本,它仍在不断发展。 – 2009-12-29 13:33:26