簡體   English   中英

JIT如何在處理集合元素的同時優化分支? (在斯卡拉)

[英]How does JIT optimize branching while processing elements of collections? (in Scala)

這是一個關於用Scala編寫的代碼性能的問題。

考慮以下兩個代碼片段,假設x是包含約5000萬個元素的集合:

def process(x: Traversable[T]) = {
   processFirst x.head
   x reduce processPair
   processLast x.last
}

與此類似(假設我們現在有一些方法可以確定我們是在第一個元素還是最后一個元素上運行):

def isFirstElement[T](x: T) = ???
def isLastElement[T](x: T) = ???

def process(x: Traversable[T]) = {
   x reduce { 
     (left, right) => 
       if (isFirstElement(left)
         processFirst(left)
       else if (isLastElement(right))
         processLast(right)

       processPair(left, right)
   }
}

哪種方法更快? 對於約5000萬個元素,速度快多少?

在我看來,第一個例子會更快,因為除了第一個和最后一個元素之外,所有條件檢查都會發生。 然而,對於后一個示例,有一些論點表明JIT可能足夠聰明,可以優化除了第一個/最后一個元素之外的所有其他頭部/最后條件檢查。

JIT是否足夠聰明地執行此類操作? 后一種方法的明顯優點是所有業務都可以放在同一個函數體中,而在后一種情況下,業務必須分成三個單獨調用的獨立函數體。

** 編輯 **

感謝所有的好評。 當我離開上面的第二個代碼片段來說明它的不正確性時,我想略微修改第一種方法以更好地反映我試圖解決的問題:

// x is some iterator
def process(x: Iterator[T]) = {
   if (x.hasNext)
   {
       var previous = x.next
       var current = null
       processFirst previous
       while(x.hasNext)
       {
          current = x.next
          processPair(previous, current)
          previous = current
       }
       processLast previous
   }
}

雖然正文中沒有進行額外的檢查,但還有一個額外的參考分配似乎是不可避免的(先前=當前)。 這也是一種更加迫切需要的方法,它依賴於可空的可變變量。 以功能性和高性能的方式實現這一點將是另一個問題的另一個練習。

這段代碼片段如何與上面兩個例子中的最后一個疊加? (包含所有分支的單迭代塊方法)。 我意識到的另一件事是,兩個示例中的后一個也在包含少於兩個元素的集合上被破壞。

如果您的底層集合具有廉價的headlast一種方法(對於通用的Traversable不是這樣),並且減少操作相對便宜,那么第二種方式比我的機器上的第一種方式花費大約10%(可能少一點)。 (您可以使用VAR來獲得first ,你可以不斷更新第二遠用正確的參數,以獲得last ,然后做循環外最后的操作。)

如果你有一個昂貴的last (即你必須遍歷整個集合),那么第一個操作需要大約10%(可能多一點)。

大多數情況下,你不應該過多擔心它,而是更擔心正確性。 例如,在2元素列表中,您的第二個代碼有一個錯誤(因為有一個else而不是單獨的測試)。 在1元素列表中,第二個代碼根本不會調用reduce的lambda,因此再次無法工作。

這是爭論你應該第一種方式,除非你確定在你的情況下last的確是昂貴的。


編輯:如果您使用迭代器切換到手動類似減少操作,那么與昂貴的last一種情況(例如列表)相比,您可能能夠節省大約40%的時間。 對於便宜的last ,可能沒那么多(高達~20%)。 (例如,在操作字符串長度時,我會得到這些值。)

首先,請注意,根據Traversable的具體實現,執行類似x.last可能非常昂貴。 比如,比這里發生的所有其他事情都要貴。

其次,我懷疑條件本身的成本是否會引人注目,即使在一個5000萬的集合上,但實際上確定一個元素是第一個還是最后一個,可能會再次,取決於實現,變得昂貴。

第三,JIT將無法優化條件:如果有辦法做到這一點,那么你就可以在沒有條件的情況下編寫你的實現。

最后,如果您開始看起來像額外的if語句可能會影響性能,您可能會考慮切換到java甚至“C”。 不要誤會我的意思,我喜歡scala,它是一種很棒的語言,具有很多功能和有用的功能,但超快速只是不是其中之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM