2016-05-06 13 views
15

मैं निम्न विधि के लिए एक डबल सरणी परिवर्तित करने के लिए है List<string> एक:सी # Double.ToString() प्रदर्शन मुद्दा

static Dest Test(Source s) 
    { 
     Dest d = new Dest(); 

     if (s.A24 != null) 
     { 
      double[] dd = s.A24; 

      int cnt = dd.Length; 

      List<string> lst = new List<string>(); 

      for (int i = 0; i < cnt; i++) 
       lst.Add(((double)dd[i]).ToString()); 

      d.A24 = lst; 
     } 
     else 
     { 
      d.A24 = null; 
     } 

     return d; 
    } 

एक पाश में एक List.Add() कर के अनुसार सबसे तेज़ तरीका है की तरह लगता है मेरी बेंचमार्क सभी विभिन्न LINQ और कन्वर्ट चाल को मार रहा है।

यह वास्तव में धीमा है। एक लाख कॉल के लिए 2400ms (कोई भी CPU, 64-बिट पसंद करते हैं)। तो मैं इसे तेजी से बनाने के विभिन्न तरीकों से प्रयोग कर रहा था। आइए मान लीजिए कि मैं स्रोत या dest सूचियों आदि को कैश नहीं कर सकता हूं।

तो वैसे भी, मैंने यहां कुछ अजीब चीज़ों पर ठोकर खाई ... अगर मैं lst को बदलता हूं।() लाइन को डबल के बजाय दशमलव पर डालने के लिए जोड़ें, यह बहुत तेज़ है। 900 एमएस बनाम 2400 एमएमएस।

यहाँ मेरे सवालों

1) दशमलव डबल अधिक सटीकता है तो है, तो मैं प्रकार इस फिल्म में कुछ भी, सही खोना नहीं चाहिए?

2) दशमलव क्यों है। ToString() इतना तेज़ है तो Double.ToString()?

3) क्या यह एक उचित अनुकूलन है, या क्या मुझे कुछ महत्वपूर्ण विवरण याद आ रहा है जहां यह मुझे काटने के लिए वापस आ जाएगा?

मैं थोड़ा और स्मृति का उपयोग करने के बारे में चिंतित नहीं हूं, मैं केवल प्रदर्शन के बारे में चिंतित हूं।

कुछ भी नहीं है इस बिंदु पर परीक्षण डाटा के लिए परिष्कृत, बस का उपयोग कर:

s.A24 = new double[] { 1.2, 3.4, 5.6 }; 
+1

क्या आप एक [mcve] पोस्ट कर सकते हैं? वैसे, जब आप dd.Length का उपयोग कर सकते हैं तो 'dd.Count()' को कॉल करने के लिए LINQ का उपयोग करना अनावश्यक है। – nvoigt

+0

'lst.AddRange (dd.Select (x => x.ToString())); 'कोई तेज़? –

+2

मूल्य क्या हैं, आपको उनसे कितना सटीकता चाहिए, और आपको किस प्रारूप में उनकी आवश्यकता है? (मैं वैसे ही वही व्यवहार देखता हूं ...) –

उत्तर

2

क्या इसके लायक है के लिए, मैं भाग गया के बाद और अलग परिणाम, दशमलव के साथ आमतौर पर थोड़ी अधिक समय लग रहा हो गया है (लेकिन दोनों के कॉल lst.Add() और संख्या.ToString() लगभग बराबर होने के लिए कॉल)।

आपके कोड में ए -24 किस प्रकार का संग्रह है? मुझे आश्चर्य नहीं होगा अगर आप जो अतिरिक्त ओवरहेड देख रहे हैं वह वास्तव में कास्टिंग या ऐसा कुछ है जिसे आप वर्तमान में नहीं देख रहे हैं।

var iterations = 1000000; 

var lst = new List<string>(); 

var rnd = new Random(); 
var dblArray = new double[iterations]; 
for (var i = 0; i < iterations; i++) 
    //INTERESTING FINDING FROM THE COMMENTS 
    //double.ToString() is faster if this line is rnd.NextDouble() 
    //but decimal.ToString() is faster if hard-coding the value "3.5" 
    //(despite the overhead of casting to decimal) 
    dblArray[i] = rnd.NextDouble(); 

var sw = new Stopwatch(); 
sw.Start(); 
for (var i = 0; i < iterations; i++) 
    lst.Add(dblArray[i].ToString()); 
sw.Stop(); 
//takes 280-300 MS 
Debug.WriteLine("Double loop MS: " + sw.ElapsedMilliseconds); 

//reset list 
lst = new List<string>(); 
sw.Restart(); 
for (var i = 0; i < iterations; i++) 
    lst.Add(((decimal)dblArray[i]).ToString()); 
sw.Stop(); 
//takes 280-320 MS 
Debug.WriteLine("Decimal loop MS: " + sw.ElapsedMilliseconds); 
+1

आप दशमलव * अंकगणित * कर रहे हैं ... साथ ही ओपी नहीं है। वे सिर्फ मौजूदा 'डबल' मान कास्टिंग कर रहे हैं। –

+1

दूसरा 'sw.Start()' कॉल गलत है। इसे 'पुनरारंभ करें() 'में बदलें। –

+0

आप सभी सही हैं! धन्यवाद! मैं कभी-कभी SO उत्तर के साथ बहुत तेज़ी से/ढीला कोड करता हूं। : -/ – Colin

1

एक दशमलव और डबल अक्सर भ्रमित और इंटरचेंज होते हैं, लेकिन वे प्रोसेसर स्तर पर पूरी तरह से अलग जानवर होते हैं। अगर मुझे डबल। ToString() के लिए कोड लिखने की कल्पना करनी पड़ी, तो मैं समस्या देख सकता हूं ... यह मुश्किल है। तुलनात्मक रूप से, दशमलव के लिए कोड लिखना। ToString() Int32.ToString() से कहीं अधिक कठिन नहीं होना चाहिए। मुझे यकीन है कि यदि आप Int32.ToString() से दशमलव तक की तुलना करते हैं। ToString() आप पाएंगे कि वे परिणाम बहुत करीब हैं।

एफवाईआई: डबल और फ्लोट (सिंगल) सटीक नहीं हैं, और कई संख्याओं को डबल में व्यक्त नहीं किया जा सकता है। आपके उदाहरण में, आप 1.2 देते हैं जो वास्तव में 1 + 1/5 है। यह एक वास्तविक डबल के रूप में अस्तित्व में नहीं हो सकता है (भले ही इसके लिए वीएस आईडीई कवर हो)। आपको 1.1 99 99 99 99 99 99 998 की तरह कुछ मिल जाएगा। यदि आप प्रदर्शन चाहते हैं, तो दशमलव का उपयोग करें।

+0

मेरे सिस्टम पर, 'दशमलव। टॉस्ट्रिंग (CultureInfo.InvariantCulture) 'Int32.ToString (CultureInfo.InvariantCulture)' के रूप में धीमी गति से 1.6 गुना है; 'Double.ToString (CultureInfo.InvariantCulture)' धीमी गति से 3.5 गुना है (एक सरल 'स्टॉपवॉच'-फांसी लूप के साथ परीक्षण किया गया, कोई 'सूची' शामिल नहीं है। तो आप बहुत दूर नहीं हैं, हालांकि "बहुत करीब" एक असाधारण का थोड़ा सा है। –

+0

डर्न ... हाँ, मुझे लगता है कि दशमलव कास्ट करना 99% मामलों के लिए काम करेगा। दशमलव पूर्ण सटीकता पर स्थानिक बिंदु भी पकड़ सकता है। मान लीजिए मुझे सिर्फ डबल ओवरहेड के साथ रहना होगा। वास्तव में Double.ToString() के लिए कोड को नहीं देख सकता क्योंकि .NET वास्तव में प्रारूपण करने के लिए सीएलआर के अंदर मूल विधि को कॉल करता है। – SledgeHammer

+0

इसके अलावा, एक अन्य दिलचस्प नोट, यदि आप 32 बिट पसंद करते हैं, तो कोड 2433ms बनाम 2400ms अधिक तेज़ है। – SledgeHammer

0

2) decimal.ToString() इतनी तेज क्यों है तो Double.ToString()?

  1. क्योंकि Double.ToString() वास्तव में और अधिक जटिल है।Decimal.ToString() और Double.ToString(), Decimal.ToString() के मूल कार्यान्वयन की तुलना सटीकता तय की गई है जबकि Double.ToString() की परिशुद्धता मांग पर है। Double में IEEE floating point definition है जो Decimal से भी अधिक जटिल है।

  2. वर्तमान Double.ToString() कार्यान्वयन _ecvt पर विंडोज और snprintf on Linux पर निर्भर करता है। वे अक्षम हैं (विशेष रूप से लिनक्स कार्यान्वयन के लिए)। को Double.ToString() को फिर से लिखने के लिए एक कुशल तरीके से लिखने के लिए _ecvt और snprintf की निर्भरता को हटा दें।

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