![](/img/trans.png)
[英]What are the performance characteristics between curried, partially applied, and 'normal' functions in Scala?
[英]Haskell are partially applied functions faster?
我在和Haskell玩弄,想知道這兩個函數之間的性能是否有任何差異:
count :: (Eq a) => [a] -> a -> Int
count xs e = foldr countCheck 0 xs
where countCheck x
| x == e = (1+)
| otherwise = (0+)
count' :: (Eq a) => [a] -> a -> Int
count' xs e = foldr countCheck 0 xs
where countCheck x acc
| x == e = acc + 1
| otherwise = acc
我嘗試使用以下代碼作為基准: main = print (count [1..10000] 1)
,這導致第一個(使用部分應用+
)函數的平均速度略快。
我主要想知道,因為對我而言, count
比“ count'
更令人困惑。 除了“聰明”之外,我還認為必須要權衡的是它更快。 那么使用部分應用的函數是否會使代碼運行更快? 如果是這樣,為什么?
好吧,我從以下程序中了解了核心
main = print (count [1..100000] 1)
和
main = print (count' [1..100000] 1)
編譯這些文件並修飾生成的內核將得到幾乎相同的文件,由於它們是相同的,因此我刪除了關於[1..10000]
和print
的不感興趣的部分。
計數:
main_e = __integer 1
main7 = \ x -> x
main6 =
\ a -> case a of _ { I# b -> I# (+# 1 b) }
main5 =
\ x ->
case eqInteger x main_e of _ {
False -> main7;
True -> main6
}
計數':
main_e = __integer 1
main5 =
\ x acc ->
case eqInteger x main_e of _ {
False -> acc;
True -> case acc of _ { I# x1 -> I# (+# x1 1) }
}
因此它實際上生成幾乎相同的核心,而count
生成稍微復雜一些的核心。 但是,將main6
和main7
內聯並把lambda抽象提升為一個,就可以得到完全相同的核心。
由於GHC可以執行所有優化,因此我對代碼性能之間的任何差異感到非常驚訝。 如果它支持count
那就更加驚訝了。
Haskell的整個禪意就是編寫干凈的程序,並讓編譯器處理得更快。 如果非文件foldr
版本更清晰,請寫下。 但是在閱讀fold
幾年之后, foldr
版本看起來更清晰了,所以我寫了。 不過很酷的部分是,使用哪種都無所謂,因為它們都被編譯為相同的代碼。
在經過足夠高的優化程度編譯的程序中使用部分應用的函數很難使它們變快,而只會變慢。 只是因為在這種情況下,您為編譯器提供了有關意圖的較少信息。
例外情況是,如果為部分應用的函數指定了名稱和INLINE
編譯指示(在某些特殊情況下)。 這是對GHC的一種暗示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.