虛函式所造成的效能損失

2021-06-22 19:46:22 字數 1023 閱讀 7682

假設在乙個執行緒同步環境中,有類似下面所示的**段:

//進入執行緒同步

nnum++;

//退出執行緒同步

以win32為例,如我們所知,執行緒同步工具有臨界區,互斥體,訊號量。我們可以任意選擇乙個,為了簡單很可能我們就選擇了臨界區。假如我們需要同步的**非常簡單,我非常建議不需要使用c++的任何功能。但是,很可能沒這麼幸運,很可能你的**會被很多人修改,很可能同步的時候需要異常退出,很可能同步的裡面還有點邏輯處理,很可能你在退出的時候沒有釋放鎖。那麼你就悲劇了。

c++在這裡一點上就體現出了與生俱來的優勢,建構函式和析構函式。假如我們把獲得鎖寫進建構函式裡面,釋放鎖寫進析構函式裡面,就能保證任意情況的退出之前都能夠釋放鎖,從而不會造成死鎖。

還有個問題是我們應該如何實現這些不同的同步工具。如果,我們分別寫三個類,ccriticalsection,cmutex,csemaphore,這三個類不是繼承自同乙個基類的,而且這三個類裡面也沒有任何的虛函式,而且我們把操作都寫成內聯的。那麼,在效率上與直接用c相比基本沒有差別。因為,所有額外的呼叫開銷都內聯了。在不喪失效率的同時保持了靈活性,這確實是非常強大的地方。

萬一你說為了靈活性,需要讓這三個類繼承同乙個基類,cbaselock,同時需要把析構函式定義成虛的,這樣就會造成很多額外的效能損失。比如,可能需要構造和析構基類物件,需要初始化虛函式指標,執行階段需要通過虛函式指標間接呼叫,還有乙個最重要的損失,編譯器無法內聯虛函式,如果虛函式比較小,那麼相對於原來的情況,這是乙個巨大的效能損失。某種意義上,我們可以忽視,基類物件的構造和析構,以及虛函式指標的初始化和呼叫時刻的間接定址,因為這些可以其它方面的因素來抵消。

但是,無法內聯乙個小的函式所造成的額外開銷是很大的。想象一下,比如剛才幾個類裡面的析構函式只是釋放鎖這乙個操作,肯定是可以內聯的,但是現在寫成虛函式了,就無法內聯了,如果這個函式被呼叫很多次,比如幾百萬次,和原來消耗的時候相比,肯定是天壤之別了,因為原來沒有函式呼叫開銷,現在有,而且因為函式內部操作太少了,函式呼叫開銷所佔據的比例非常大,所以你的設計造成了巨大的效能損失。

Focal loss損失函式 所解決的問題

解決的問題 消除正負樣本比例不平衡 one stage演算法需要產生超大量的預選框,模型被大量負樣本所主導,focal loss對此種情況卓有成效。並且挖掘難負樣本 難負樣本即為一些很難區分是正樣本還是負樣本的負樣本 其對立的就是一些簡單的負樣本,很容易區分出來是負樣本,其前向傳播的loss很小,模...

gan網路損失函式 GAN的損失函式

理解生成對抗網路的關鍵在於理解gan的損失函式 js散度 gan實際是通過對先驗分布施加乙個運算g,來擬合乙個新的分布 如果從傳統的判別式網路的思路出發,只要選定合適的loss,就可以使生成分布和真實分布之間的距離盡可能逼近 kl散度經常用來衡量分布之間距離 但kl散度是不對稱的。不對稱意味著,對於...

GetHashCode函式所存在的陷阱

gethashcode函式,看了它的名字就知道它會被用在 沒錯,這個函式一般是在操作hashtable或者dictionary之類的資料集的時候被呼叫。每個型別,不管是值型別還是引用型別,都提供這個基本函式,同樣也可以像重寫tostring或者equals函式一樣去重寫它。但是我這裡要說的,不建議重...