2010-03-06 9 views
6

मेरे other question से संबंधित, अब मैंने एसओआर (लगातार ओवर-रिलीक्सेशन) विधि का उपयोग करने के लिए स्पैर मैट्रिक्स सॉल्वर को संशोधित किया है। कोड इस प्रकार अब है:इस एसओआर सॉल्वर की गति इनपुट पर निर्भर क्यों करती है?

void SORSolver::step() { 
    float const omega = 1.0f; 
    float const 
     *b = &d_b(1, 1), 
     *w = &d_w(1, 1), *e = &d_e(1, 1), *s = &d_s(1, 1), *n = &d_n(1, 1), 
     *xw = &d_x(0, 1), *xe = &d_x(2, 1), *xs = &d_x(1, 0), *xn = &d_x(1, 2); 
    float *xc = &d_x(1, 1); 
    for (size_t y = 1; y < d_ny - 1; ++y) { 
     for (size_t x = 1; x < d_nx - 1; ++x) { 
      float diff = *b 
       - *xc 
       - *e * *xe 
       - *s * *xs - *n * *xn 
       - *w * *xw; 
      *xc += omega * diff; 
      ++b; 
      ++w; ++e; ++s; ++n; 
      ++xw; ++xe; ++xs; ++xn; 
      ++xc; 
     } 
     b += 2; 
     w += 2; e += 2; s += 2; n += 2; 
     xw += 2; xe += 2; xs += 2; xn += 2; 
     xc += 2; 
    } 
} 

अब अजीब बात है: अगर मैं omega (छूट कारक) में वृद्धि, निष्पादन की गति विभिन्न सरणियों के अंदर मूल्यों पर नाटकीय रूप से निर्भर करने के लिए शुरू होता है!

omega = 1.0f के लिए, निष्पादन समय कम या ज्यादा स्थिर है। omega = 1.8 के लिए, पहली बार, यह आमतौर पर step() 10 बार निष्पादित करने के लिए 5 मिलीसेकंड ले जाएगा, लेकिन यह धीरे-धीरे सिमुलेशन के दौरान लगभग 100 एमएस तक बढ़ जाएगा। अगर मैं omega = 1.0001f सेट करता हूं, तो मुझे निष्पादन समय में तदनुसार मामूली वृद्धि दिखाई देती है; उच्च omega चला जाता है, सिमुलेशन के दौरान तेज़ निष्पादन समय बढ़ जाएगा।

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

यह यूएसंटू पर जी ++ के साथ-साथ 64-बिट विंडोज 7 पर पुन: उत्पन्न होता है जब वीएस -2008 के साथ 32-बिट्स के लिए संकलन करते हैं।

मैंने सुना है कि NaN और Inf मूल्य फ़्लोटिंग पॉइंट गणनाओं के लिए धीमे हो सकते हैं, लेकिन कोई NaNs या Infs मौजूद नहीं हैं। क्या यह संभव है कि फ्लोट कंप्यूटेशंस की गति इनपुट नंबरों के मूल्यों पर निर्भर करती है?

+0

क्या आप वाकई कुछ अन्य कोडपैथ को मापते हैं जो गणना के मूल्यों पर निर्भर करते हैं? – ebo

+0

यदि आपके पास प्रदर्शन समस्याएं हैं, तो इन गणनाओं के लिए GPU का उपयोग करने पर विचार करें। जीपीयू स्पैस मैट्रिक्स काम पर बहुत अच्छे हैं। – Mark

+0

@ebo: मैंने केवल इस कॉल को मापने के लिए लिनक्स में रीयल-टाइम घड़ी का उपयोग किया था। तो हाँ, मुझे पूरा यकीन है। – Thomas

उत्तर

5

आपके अंतिम प्रश्न का संक्षिप्त उत्तर "हां" है - denormalized (शून्य के बहुत करीब) संख्याओं को विशेष हैंडलिंग की आवश्यकता होती है और बहुत धीमी हो सकती है। मेरा अनुमान है कि वे सिमुलेशन में रेंग रहे हैं जैसे समय चल रहा है। इस संबंधित एसओ पोस्ट को देखें: Floating Point Math Execution Time

शून्य पर फ्लश करने के लिए फ्लोटिंग-पॉइंट नियंत्रण सेट करना सिमुलेशन गुणवत्ता पर नगण्य इम्पैक्ट के साथ चीजों का ख्याल रखना चाहिए।

+0

denormalized मूल्य वास्तव में इसमें शामिल हो रहे हैं; मैं जितना संभव हो सके शून्य के करीब विचलन ('d_b' ऊपर) प्राप्त करने के लिए द्रव दबाव के लिए हल कर रहा हूं। तो यह बताता है, और आपने एक बार मुझे कुछ सिखाया है। बहुत धन्यवाद!('1-ओमेगा' के बारे में आपका भ्रम शायद इसलिए है क्योंकि मैट्रिक्स पंक्तियों को स्केल किया गया है, इसलिए विकर्ण पर' 1' है। '- * xc' वहां से नहीं आया है, लेकिन वास्तव में शब्द '-मेगा * * है xc' कोड की आपकी लाइन में। मुझे उचित उत्तर मिल रहे हैं।) – Thomas

+0

खुशी है कि चाल है। मैंने हाल ही में एक सहकर्मी से एक डरावनी कहानी सुनाई - कुछ साल पहले एक बड़े व्यापार शो से ठीक पहले, डेमो प्रोग्राम कुछ मिनटों के लिए दौड़ने के बाद एक क्रॉल में धीमा हो रहा था। यह ग्राफिक्स ड्राइवर में एक बग ठीक से फ़्लोटिंग-पॉइंट नियंत्रण ध्वज को रीसेट नहीं कर रहा था, और कठोर शरीर सिमुलेशन में एक धुंधला कारक के दोहराव गुणा से denormals मिल रहा था। समस्या को जानने के बाद उन्हें ठीक करने के लिए पर्याप्त सरल, लेकिन इसे ट्रैक करने के लिए उन्हें एक या दो दिन डिबगिंग ले लिया। वैसे भी, मैंने तुरंत सोचा कि जब मैं आपका विवरण पढ़ता हूं। – celion

+0

मैंने जवाब को स्पष्ट करने के लिए 1 (ओमेगा) के बारे में अपने (गलत) संपादन भी हटा दिए ... – celion

0

celion's answer सही साबित होता है। पोस्ट वह के लिए लिंक पर फ्लश-टू-जीरो denormalized मूल्यों की बारी करने के कहते हैं:

#include <float.h> 
_controlfp(_MCW_DN, _DN_FLUSH); 

बहरहाल, यह विंडोज ही है। लिनक्स पर जीसीसी का उपयोग करना, मैं इनलाइन विधानसभा का एक एहसास के साथ ऐसा ही किया था:

int mxcsr; 
__asm__("stmxcsr %0" : "=m"(mxcsr) : :); 
mxcsr |= (1 << 15); // set bit 15: flush-to-zero mode 
__asm__("ldmxcsr %0" : : "m"(mxcsr) :); 

यह मेरी पहली 86 विधानसभा कभी तो यह शायद सुधार किया जा सकता। लेकिन यह मेरे लिए चाल है।

+0

आप fenv.h (सी 99) के साथ एफपी पर्यावरण को पोर्टेबल सेट कर सकते हैं। – Jed

+0

यह सी ++ है, इसलिए यह सीधे काम नहीं करेगा। लेकिन उस कार्यान्वयन को चुरा लेना संभव हो सकता है। धन्यवाद! – Thomas

संबंधित मुद्दे

 संबंधित मुद्दे