दस्तावेज़ीकरण यदि इस शब्द के उपयोग से भरा है, उदा।

Pseudo expression providing partial reduction operations
Pseudo expression providing matrix output with given format

लेकिन मुझे इसका अर्थ नहीं मिल रहा है।

1
NoSenseEtAl 15 अप्रैल 2021, 17:11

2 जवाब

सबसे बढ़िया उत्तर

मेरा मानना ​​है कि Eigen प्रलेखन जिसे "छद्म भाव" के रूप में संदर्भित करता है, वास्तव में "अभिव्यक्ति टेम्पलेट के उदाहरण हैं। ".

गणित पुस्तकालयों, या किसी भी डोमेन में वास्तव में पुस्तकालयों जैसी चीजों को लागू करते समय अभिव्यक्ति टेम्पलेट्स का उपयोग सी ++ में एक आम तकनीक है जहां यह उम्मीद की जाती है कि उपयोगकर्ता एक मूल्य बनाने के लिए कई गणनाओं को एक साथ जोड़ देंगे।

अभिव्यक्ति टेम्पलेट्स का विचार यह है कि वे गणना को तब तक स्थगित करने का एक तरीका हैं जब तक कि गणना वास्तव में आवश्यक न हो और गणना को वास्तव में कैसे किया जाता है, इस पर अतिरिक्त नियंत्रण की अनुमति मिलती है। यदि इनपुट तर्कों को बदले बिना पूरी गणना आइटम द्वारा आइटम की जा सकती है, तो आपको अस्थायी रूप से बड़ी वस्तु के लिए स्मृति आवंटित करने की आवश्यकता नहीं हो सकती है।

वैसे भी जहाँ तक Eigen का उपयोगकर्ता होने की बात है, आपको वास्तव में एक विवरण को छोड़कर इसके अभिव्यक्ति टेम्पलेट्स के उपयोग को समझने की आवश्यकता नहीं है। कभी भी ऐसा कोड न लिखें जो इस तरह दिखता हो:

auto to_canonical_coords = get_rotation_matrix(theta) * get_translation_matrix(offset);

समस्या एक ऑपरेशन पर टाइप डिडक्शन करने के साथ है, operator* यहाँ, जो एक एक्सप्रेशन टेम्प्लेट इंस्टेंस देता है। एक्सप्रेशन टेम्प्लेट इंस्टेंस का उद्देश्य अल्पकालिक होना है; इस तरह का एक असाइनमेंट एक वेरिएबल के लिए एक एक्सप्रेशन टेम्प्लेट इंस्टेंस असाइन करेगा जहां यह उन ऑब्जेक्ट्स को आउटलिव कर सकता है जो इसे संदर्भ से संदर्भित करता है या अन्य समस्याओं का कारण बनता है। इसके बजाय ऊपर की तरह लिखें

Eigen::Matrix<double, 3, 3> to_canonical_coords = get_rotation_matrix(theta) * get_translation_matrix(offset);

या समतुल्य Eigen::Matrix<double, 3, 3> के लिए एक प्रकार के उपनाम का उपयोग कर रहा है।

Eigen दस्तावेज़ में यहां समस्या का उल्लेख है। साथ ही मेरा मानना ​​है कि स्कॉट मेयर्स इस मुद्दे पर आम तौर पर प्रभावी आधुनिक C++ कहीं पर चर्चा करते हैं।

7
jwezorek 19 अप्रैल 2021, 19:37

मुझे लगता है कि एक उदाहरण यह दिखाने का एक अच्छा तरीका है कि यह कैसे काम करता है। इस तरह एक कोड स्निपेट की कल्पना करें:

void print_types(const Eigen::Matrix<double, 3, 3>& test) {
    std::cout << typeid(test).name() << "\n";
    std::cout << typeid(test.transpose()).name() << "\n";
    std::cout << typeid(test.transpose().eval()).name() << "\n";
}

अभिव्यक्ति टेम्पलेट प्रोग्रामिंग Eigen के बिना, आप इन तीनों से एक ही चीज़ को प्रिंट करने की अपेक्षा करेंगे: Eigen::Matrix<double, 3, 3>

लेकिन ट्रांसपोज़ ऑपरेशन को वास्तव में तब तक मूल्यांकन करने की आवश्यकता नहीं है जब तक इसका उपयोग नहीं किया जा रहा है - जैसे कि यदि आप AT * B करते हैं, तो आपको वास्तव में कभी भी स्टोर करने की आवश्यकता नहीं होगी ट्रांसपोज़्ड A मैट्रिक्स, आप बस इस क्रम को बदल सकते हैं कि आप प्रविष्टियों को कैसे गुणा करते हैं। तो दूसरे प्रिंटआउट का वास्तविक विघटित परिणाम Eigen::Transpose> है। Eigen::Transpose<...> सामान्य Eigen::Matrix के समान ही व्यवहार करता है लेकिन वास्तव में ट्रांसपोज़ की गणना की आवश्यकता नहीं होती है। साधारण 3x3 मैट्रिसेस के लिए शायद यह ज्यादातर समय बहुत बड़ा सुधार नहीं है, लेकिन विशाल मैट्रिस के लिए गणना को छोड़कर बहुत बड़ा प्रदर्शन लाभ हो सकता है।

.eval() (तीसरे प्रिंटआउट की तरह) को कॉल करने से कोई भी मध्यवर्ती Eigen प्रकार वापस वास्तविक मैट्रिक्स प्रकार (वास्तव में गणना करके) में बदल जाएगा, इसलिए तीसरी पंक्ति उसी Eigen::Matrix<double, 3, 3> को प्रिंट करेगी।

यह अन्य भावों के साथ भी काम करता है, जैसे typeid(test * test + test).name() के लिए, आप देखेंगे:

Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double, double>, Eigen::Product<Eigen::Matrix<double, 3, 3, 0, 3, 3>, Eigen::Matrix<double, 3, 3, 0, 3, 3>, 0> const, Eigen::Matrix<double, 3, 3, 0, 3, 3> const>

जो Eigen को बेहतर ढंग से अनुकूलित करने की अनुमति देता है कि अंतिम परिणाम की गणना कैसे की जाती है लेकिन किसी भी मध्यवर्ती गणना को छोड़ दिया जाता है।

मुझे आशा है कि यह समझ में आता है, अगर नहीं तो टिप्पणी करने के लिए स्वतंत्र महसूस करें!

2
mattlangford 15 अप्रैल 2021, 16:04