[問題] 為什麼CRTP+variant還是比virtual快很多

作者: ab4daa (nooooooooooooooooooo)   2020-01-02 12:27:59
一開始是看到這篇2013的文章
https://eli.thegreenplace.net/2013/12/05/
the-cost-of-dynamic-virtual-calls-vs-static-crtp-dispatch-in-c/
短: https://reurl.cc/M75jGK
裡面只用一個CRTP impl 所以compiler可以直接inline
但是我實際用到virtual是像這樣
集中一堆ABC然後全呼叫一遍:
vector<ABC*> bases;
for(auto& it : bases)
it->virtual_func();
改成CRTP的寫法大概像這樣:
https://godbolt.org/z/LygFKT
我的想像是
visit時不是應該也要先看實際型別是甚麼
再呼叫相對應函數嗎
這跟vtable的行為很像吧
為什麼量測時間 CRTP還是比virtual快了5~7倍?
(i5 7400 + vs2019)
我的程度看組語或是看variant header都很痛苦
所以來洗耳恭聽大大的教訓
感恩
作者: Lipraxde (Lipraxde)   2020-01-02 21:04:00
Vvistor 裡的那個 for loop 被優化掉了,155 行的沒有https://kheresy.wordpress.com/2017/10/16/cpp17-variant/ <- 我覺得介紹的不錯
作者: loveme00835 (髮箍)   2020-01-02 23:09:00
variant 做的事情就是用 type code 判斷然後再轉型,而轉型後實際上呼叫的函式是在編譯時期就選好的, 你可以自己用 union + type code 實作看看
作者: LPH66 (-6.2598534e+18f)   2020-01-03 04:51:00
CRTP 的「基類」並不是單一個類, 而是每個子類都有一個基類也因此雖然看起來同一段程式碼被很多不同子類呼叫但因為基類是模版的關係, 每個基類是分開的這個基類在呼叫子類方法時會確定知道自己負責什麼子類(藉由 CRTP 繼承時給的模版參數, 所以也是編譯期就確定的)因此可以省去執行所有判斷子類的操作 (如 vtable 等)甚至因為子類型態確定, 呼叫當下的所需要的繼承相關操作僅僅只有為求得子類實體的 downcast 而已這個 downcast 也因為是 static_cast 基本上沒有判斷操作簡單說就是, 藉由模版把子類型態判斷變成編譯器的模版選擇
作者: saladim (殺拉頂)   2020-01-07 01:47:00
請問個蠢問題...為什麼tick() function沒有name hiding的問題阿? 謝謝~有時會被要求compiler warning要全修...

Links booklink

Contact Us: admin [ a t ] ucptt.com