2009-12-29 77 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