दिलचस्प पोस्ट
कैसे नियंत्रक कार्रवाई विधि के लिए प्रोग्राम को स्पष्ट रूप से साफ़ करें मैं पूरी तरह से टीएफएस बाइंडिंग कैसे निकाल सकता हूं? PHP कोड निष्पादित नहीं किया जा रहा है, बजाय पृष्ठ पर कोड दिखाता है WPF के साथ एक लॉग दर्शक लागू करना मैं अपने डब्लूसीएफ सेवा पर कन्स्ट्रक्टर को कैसे मान दूं? एक डीव्ही ब्लॉक के अंदर सीएसएस केंद्र पाठ (क्षैतिज और अनुलंब) एनजी-वी बनाम एनजी-शो / एनजी-छिपाने के लिए कब? मैं पर्ल में एक सरणी से डुप्लिकेट आइटम कैसे निकालूं? अजगर में आइटम आवृत्ति गणना कैसे win32 कंसोल ANSI / VT100 एस्केप दृश्यों को पहचानने के लिए? मैं ऑब्जेक्ट को किसी सरणी में कैसे रूपांतरित कर सकता हूं? आपको जेफ्राम और अन्य घटकों का विस्तार क्यों नहीं करना चाहिए? सी और सी ++ में अंकगणित संचालन से पहले एक इंट को क्यों बदलना चाहिए? एन्जेरियल जेएसएस एक्सेस स्कोप बाहर जेएस फ़ंक्शन से वेक्टर के लिए वैकल्पिक <bool>

बेहतर प्रदर्शन करने के लिए IOStream कैसे प्राप्त करें?

अधिकांश सी ++ उपयोगकर्ताओं ने सी / सी के कार्यों के printf / scanf परिवार का उपयोग करना पसंद किया सी भी जब वे C ++ में कोडिंग कर रहे हैं

यद्यपि मैं मानता हूं कि मुझे इंटरफ़ेस का रास्ता बेहतर (विशेषकर पॉसिक्स जैसा प्रारूप और स्थानीयकरण) लगता है, ऐसा लगता है कि एक भारी चिंता प्रदर्शन है

इस प्रश्न को ध्यान में रखते हुए:

मैं एक फ़ाइल के लाइन पढ़ने के द्वारा लाइन को कैसे गति कर सकता हूं

ऐसा लगता है कि सबसे अच्छा जवाब fscanf का उपयोग करना है और सी ++ ifstream लगातार 2-3 गुना धीमे है

मैंने सोचा कि यह महान होगा अगर हम IOStreams के प्रदर्शन में सुधार करने के लिए "टिप्स" के एक संग्रह को संकलित कर सकते हैं, क्या काम करता है, क्या नहीं।

घ्यान देने योग्य बातें

  • बफरिंग ( rdbuf()->pubsetbuf(buffer, size) )
  • सिंक्रनाइज़ेशन ( std::ios_base::sync_with_stdio )
  • लोकेल हैंडलिंग (क्या हम एक ट्रिम-डाउन लोकेल का उपयोग कर सकते हैं या इसे पूरी तरह हटा सकते हैं?)

बेशक, अन्य तरीकों का स्वागत है

नोट: डायटममार कुहल द्वारा "नया" कार्यान्वयन का उल्लेख किया गया था, लेकिन मैं इसके बारे में कई विवरणों का पता लगाने में असमर्थ था। पिछला संदर्भ मृत लिंक होने लगते हैं

वेब के समाधान से एकत्रित समाधान "बेहतर प्रदर्शन करने के लिए IOStream कैसे प्राप्त करें?"

यहां तक ​​कि मैं अब तक इकट्ठा किया है:

बफरिंग :

डिफ़ॉल्ट रूप से बफर बहुत छोटा है, तो बफर आकार में वृद्धि निश्चित रूप से प्रदर्शन को बेहतर बना सकती है:

  • यह एचडीडी हिट की संख्या कम कर देता है
  • यह सिस्टम कॉल की संख्या कम कर देता है

अंतर्निहित streambuf कार्यान्वयन तक पहुंच द्वारा बफ़र सेट किया जा सकता है

 char Buffer[N]; std::ifstream file("file.txt"); file.rdbuf()->pubsetbuf(Buffer, N); // the pointer reader by rdbuf is guaranteed // to be non-null after successful constructor 

@आइवीआर की चेतावनी सौजन्य: cppreference के अनुसार, फ़ाइल खोलने से पहले pubsetbuf को कॉल करना सबसे अच्छा है। विभिन्न मानक पुस्तकालय कार्यान्वयन अन्यथा भिन्न व्यवहार हैं

लोकेल हैंडलिंग:

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

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

तुल्यकालन:

मैं इस सुविधा का उपयोग करके कोई भी प्रदर्शन सुधार नहीं देख सकता था

sync_with_stdio स्थिर फ़ंक्शन का उपयोग करके कोई वैश्विक सेटिंग ( std::ios_base का स्थिर सदस्य) का उपयोग कर sync_with_stdio है।

माप:

इस के साथ खेलना, मैंने एक साधारण प्रोग्राम के साथ ट्यूटोरियल किया है, जीओसी gcc 3.4.2 का उपयोग एसओयूई 10 पी पी-ओ 2 के साथ किया है।

सी: 7.76532e + 06
सी ++: 1.0874 ए + 07

जो डिफ़ॉल्ट कोड के लिए लगभग 20% की मंदी का प्रतिनिधित्व करता है … वास्तव में बफर (या तो सी या सी ++ में) या सिंक्रनाइज़ेशन पैरामीटर (सी ++) से छेड़छाड़ करने से कोई सुधार नहीं हुआ।

दूसरों के द्वारा परिणाम:

@ इरफ़ी ऑन जी ++ 4.7.2-2ुउन्ट्यू 1, -ओ 3, वर्चुअलाइज्ड उबुंटू 11.10, 3.5.0-25-जेनेरिक, x86_64, पर्याप्त राम / सीपीयू, 196 एमबी कई "ढूंढें / >> बड़ीफ़ाइल। टीटीटी" चलाता है

सी: 634572 सी ++: 473222

सी + + 25% तेज़ तेज़

@ मैटेओ इटालिया जी ++ 4.4.5, -ओ 3, उबंटु लिनक्स 10.10 x86_64 पर एक यादृच्छिक 180 एमबी फ़ाइल के साथ

सी: 9103 9 0
सी ++: 776016

सी ++ 17% तेज

@ बोगाटिर पर जी ++ i686-सेप-डार्विन 10-जी ++ – 4.2.1 (जीसीसी) 4.2.1 (एपल इंक का निर्माण 5664), मैक मिनी, 4 जीबी रैम, बेकार, इस परीक्षा को छोड़कर 168 एमबी डेटाफ़ाइल के साथ

सी: 4.34151 ई + 06
सी ++: 9.14476 ए + 06

सी ++ 111% धीमा

@ एएसयू पर क्लैग ++ 3.8.0-2ubuntu4, कुबंटू 16.04 लिनक्स 4.8-आरसी 3, 8 जीबी रैम, आईएएस हैसवेल, महत्वपूर्ण एसएसडी, 88 एमबी डेटाफ़ाइल (टार। एक्सज़ संग्रह)

सी: 2708 9 सी ++: 162799

सी ++ 66% तेज

तो जवाब है: यह कार्यान्वयन के मुद्दे की गुणवत्ता है, और वास्तव में मंच पर निर्भर करता है: /

बेंचमार्किंग में दिलचस्पी रखने वालों के लिए यहां कोड भरा हुआ है:

 #include <fstream> #include <iostream> #include <iomanip> #include <cmath> #include <cstdio> #include <sys/time.h> template <typename Func> double benchmark(Func f, size_t iterations) { f(); timeval a, b; gettimeofday(&a, 0); for (; iterations --> 0;) { f(); } gettimeofday(&b, 0); return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) - (a.tv_sec * (unsigned int)1e6 + a.tv_usec); } struct CRead { CRead(char const* filename): _filename(filename) {} void operator()() { FILE* file = fopen(_filename, "r"); int count = 0; while ( fscanf(file,"%s", _buffer) == 1 ) { ++count; } fclose(file); } char const* _filename; char _buffer[1024]; }; struct CppRead { CppRead(char const* filename): _filename(filename), _buffer() {} enum { BufferSize = 16184 }; void operator()() { std::ifstream file(_filename, std::ifstream::in); // comment to remove extended buffer file.rdbuf()->pubsetbuf(_buffer, BufferSize); int count = 0; std::string s; while ( file >> s ) { ++count; } } char const* _filename; char _buffer[BufferSize]; }; int main(int argc, char* argv[]) { size_t iterations = 1; if (argc > 1) { iterations = atoi(argv[1]); } char const* oldLocale = setlocale(LC_ALL,"C"); if (strcmp(oldLocale, "C") != 0) { std::cout << "Replaced old locale '" << oldLocale << "' by 'C'\n"; } char const* filename = "largefile.txt"; CRead cread(filename); CppRead cppread(filename); // comment to use the default setting bool oldSyncSetting = std::ios_base::sync_with_stdio(false); double ctime = benchmark(cread, iterations); double cpptime = benchmark(cppread, iterations); // comment if oldSyncSetting's declaration is commented std::ios_base::sync_with_stdio(oldSyncSetting); std::cout << "C : " << ctime << "\n" "C++: " << cpptime << "\n"; return 0; } 

दो और सुधार:

अंक std::cin.tie(nullptr); भारी इनपुट / आउटपुट से पहले

http://en.cppreference.com/w/cpp/io/cin का हवाला देते हुए:

एक बार std :: cin का निर्माण किया जाता है, std :: cin.tie () रिटर्न और std :: cout, और इसी तरह, std :: wcin.tie () रिटर्न & std :: wcout इसका अर्थ है कि std :: cin पर कोई स्वरूपित इनपुट ऑपरेशन std :: cout.flush () को कॉल करने के लिए मजबूर करता है यदि कोई भी अक्षर आउटपुट के लिए लंबित है।

आप std::cout से std::cout std::cin untying द्वारा बफ़र फ्लाई से बच सकते हैं। यह std::cin और std::cout लिए कई मिश्रित कॉल के साथ प्रासंगिक है। ध्यान दें कि std::cin.tie(std::nullptr); प्रोग्राम को उपयोगकर्ता द्वारा इंटरैक्टिव चलाने के लिए अनुपयोगी बनाता है, क्योंकि उत्पादन में देरी हो सकती है

प्रासंगिक बेंचमार्क:

फ़ाइल test1.cpp :

 #include <iostream> using namespace std; int main() { ios_base::sync_with_stdio(false); int i; while(cin >> i) cout << i << '\n'; } 

फ़ाइल test2.cpp :

 #include <iostream> using namespace std; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int i; while(cin >> i) cout << i << '\n'; cout.flush(); } 

दोनों g++ -O2 -std=c++11 द्वारा संकलित कंपाइलर संस्करण: g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 (हाँ, मुझे पता है, बहुत पुराना है)।

बेंचमार्क परिणाम:

 work@mg-K54C ~ $ time ./test1 < test.in > test1.in real 0m3.140s user 0m0.581s sys 0m2.560s work@mg-K54C ~ $ time ./test2 < test.in > test2.in real 0m0.234s user 0m0.234s sys 0m0.000s 

( test.in में 11 9 648 लाइन होते हैं जिनमें से प्रत्येक केवल 5 । यह 2.4 एमबी है, इसलिए यहां पोस्ट न करने के लिए खेद है।)

मुझे याद है कि एक एल्गोरिथम कार्य को सुलझाना जहां ऑनलाइन न्यायाधीश ने अपने कार्यक्रम को cin.tie(nullptr) बिना मना कर दिया था, लेकिन इसे cin.tie(nullptr) या printf / scanf बजाय cin / cout साथ स्वीकार कर रहा था।

std::endl बजाय '\n' उपयोग करें

http://en.cppreference.com/w/cpp/io/manip/endl का हवाला देते हुए:

आउटपुट अनुक्रम ओएस में एक नई पंक्ति को सम्मिलित करता है और ओएसपुट (ओ.वि.वियन ('\ n')) ओ.एस.फ़्लुश

आप एंड्रॉएल '\n' बजाय '\n' छपाई करके बफर फ्लश करने से बच सकते हैं।

प्रासंगिक बेंचमार्क:

फ़ाइल test1.cpp :

 #include <iostream> using namespace std; int main() { ios_base::sync_with_stdio(false); for(int i = 0; i < 1179648; ++i) cout << i << endl; } 

फ़ाइल test2.cpp :

 #include <iostream> using namespace std; int main() { ios_base::sync_with_stdio(false); for(int i = 0; i < 1179648; ++i) cout << i << '\n'; } 

दोनों ऊपर के रूप में संकलित

बेंचमार्क परिणाम:

 work@mg-K54C ~ $ time ./test1 > test1.in real 0m2.946s user 0m0.404s sys 0m2.543s work@mg-K54C ~ $ time ./test2 > test2.in real 0m0.156s user 0m0.135s sys 0m0.020s 

दिलचस्प है कि आप कहते हैं कि सी प्रोग्रामर सी ++ लिखते समय प्रिंटफेयर पसंद करते हैं क्योंकि मुझे बहुत सारे कोड मिलते हैं जो आउटपुट लिखने के लिए cout और iostream उपयोग करने के अलावा सी है

उपयोग अक्सर अक्सर filebuf का उपयोग करके बेहतर प्रदर्शन प्राप्त कर सकते हैं (स्कॉट मेयेर्स ने प्रभावी एसटीएल में इसका उल्लेख किया है) लेकिन फ़ाइलबफ़ प्रत्यक्ष और सबसे अधिक डेवलपर्स का इस्तेमाल करते हुए अपेक्षाकृत कम प्रलेखन है क्योंकि std::getline जो अधिक से अधिक सरल होता है।

लोकल के संबंध में, यदि आप पहलुओं को बनाते हैं तो आप अक्सर अपने प्रदर्शन के आधार पर एक स्थान बनाकर बेहतर तरीके से प्रदर्शन कर सकते हैं, इसे संग्रहीत कर रख सकते हैं, और इसे आपके द्वारा उपयोग किए जाने वाले प्रत्येक स्ट्रीम में लगा सकते हैं।

मैंने हाल ही में इस पर एक और विषय देखा था, इसलिए यह डुप्लिकेट होने के करीब है।