我正在使用DAG(有向無環圖)來表示和計算表達式;每個節點代表一個操作(+
,-
, /
,*
,積累等等),並且通過按照拓撲排序順序依次評估每個節點來實現對整個表達式的評估。根據它代表的運算符,每個節點繼承基類RefNode
並實現虛函數評估。 Node類在代表操作符的仿函數上進行模板化。節點評估順序保存在vector<RefNode*>
中,調用每個元素的->evaluate()
。在計算圖中避免虛函數調用
某些快速剖析顯示虛擬evaluate
可以從開銷或摧毀分支預測中減慢添加節點2倍[1]。
作爲第一步,將類型信息編碼爲相應的使用static_cast
的整數。這確實有幫助,但它笨重,我寧願在代碼的熱門部分跳來跳去。
struct RefNode {
double output;
inline virtual void evaluate(){}
};
template<class T>
struct Node : RefNode {
double* inputs[NODE_INPUT_BUFFER_LENGTH];
T evaluator;
inline void evaluate(){ evaluator(inputs, output); }
};
struct Add {
inline void operator()(double** inputs, double &output)
{
output=*inputs[0]+*inputs[1];
}
};
的評估可能看起來像:
Node<Add>* node_1 = ...
Node<Add>* node_2 = ...
std::vector<RefNode*> eval_vector;
eval_vector.push_back(node_1);
eval_vector.push_back(node_2);
for (auto&& n : eval_vector) {
n->evaluate();
}
我有以下問題,牢記性能是至關重要的:
- 我怎樣才能避免這種情況的虛函數?
- 如果不是,我該如何改變我表示表達式圖表的方式來支持多個操作,其中一些操作必須保持狀態,並避免虛函數調用。
- 其他框架如Tensorflow/Theano如何表示計算圖?
[1]在我的系統上進行一次加法操作需要約2.3ns的虛擬功能和1.1ns的無需。雖然這很小,但整個計算圖大部分是加法節點,因此有很大一部分時間需要保存。
你將不得不使用模板。但是,這需要在編譯時知道該圖。如果計算圖形是在運行時(例如,用戶輸入)構造的,那麼我看不到避免虛擬調用的方法。 – MadScientist
避免虛擬功能,您可能會使用奇怪的循環模板模式 –
謝謝安德魯。我確實看過@CRTP,但我很努力地看到在這種情況下我可以如何使用它。你介意擴大一點嗎? – user1893603