मुझे पता है कि बहुत सारे कंपाइलर के अनुकूलन बल्कि गूढ़ हो सकते हैं, लेकिन मेरा उदाहरण इतना सरल है कि मैं यह देखना चाहता हूं कि मैं समझ सकता हूं कि क्या मुझे समझ में आ रहा है, अगर किसी को पता है कि यह क्या कर सकता है।कंपाइलर कैसे getline() को प्रभावी ढंग से अनुकूलित करता है?
मेरे पास 500 एमबी टेक्स्ट फ़ाइल है। मैं एक fstream घोषित और प्रारंभ:
std::fstream file(path,std::ios::in)
मुझे अनुक्रमिक रूप से फ़ाइल को पढ़ने की आवश्यकता है। यह टैब सीमित है लेकिन फ़ील्ड की लंबाई ज्ञात नहीं है और रेखा से भिन्न होती है। वास्तविक पार्सिंग को मुझे प्रत्येक पंक्ति में करने की ज़रूरत है जो कुल मिलाकर बहुत कम समय में जोड़ा गया है (जो वास्तव में मुझे आश्चर्यचकित कर रहा था क्योंकि मैं स्ट्रिंग कर रहा था :: गेटलाइन से प्रत्येक पंक्ति पर ढूंढें। मैंने सोचा कि धीमा होगा)।
आम तौर पर मैं एक स्ट्रिंग के लिए प्रत्येक पंक्ति खोजना चाहता हूं, और जब मुझे लगता है तो लूप को रोकना। मैं अपनी खुद की जिज्ञासा के लिए लाइन संख्याओं को बढ़ा रहा हूं और थूक रहा हूं, मैंने पुष्टि की है कि इसमें थोड़ा समय (5 सेकंड या उससे अधिक) जोड़ता है और मुझे यह देखने देता है कि यह पिछली छोटी रेखाओं को कैसे उड़ाता है और लंबी लाइनों पर धीमा हो जाता है।
मेरे पास टेक्स्ट को अद्वितीय स्ट्रिंग के रूप में पाया जाने वाला टेक्स्ट है, इसलिए इसे प्रत्येक पंक्ति को खोजने की आवश्यकता है। मैं इसे अपने फोन पर कर रहा हूं इसलिए मैं मुद्दों को स्वरूपित करने के लिए क्षमा चाहता हूं लेकिन यह बहुत सरल है। मेरे पास एक फंक्शन को एक संदर्भ के रूप में ले जाने वाला एक फ़ंक्शन है और एक स्ट्रिंग के रूप में पाया जाने वाला टेक्स्ट और std :: size_t लौटा रहा है।
long long int lineNum = 0;
while (std::getline (file, line))
{
pos = line.find(text);
lineNum += 1;
std::cout << std::to_string(lineNum) << std::endl;
if (pos != -1)
return file.tellg():
}
return std::string::npos;
संपादित करें: लिंग्सी ने इंगित किया कि to_string यहां आवश्यक नहीं है, धन्यवाद। जैसा कि बताया गया है, लाइन नंबर गणना और आउटपुट को पूरी तरह से छोड़कर कुछ सेकंड बचाता है, जो मेरे पूर्ववर्ती उदाहरण में कुल का एक छोटा प्रतिशत है।
यह सफलतापूर्वक प्रत्येक पंक्ति के माध्यम से चलता है, और 408 सेकंड में अंत स्थिति देता है। फ़ाइल को स्ट्रिंगस्ट्रीम में डालने की कोशिश करने में मुझे न्यूनतम सुधार हुआ था, या पूरे लूप में सबकुछ छोड़ना था (केवल अंत तक कोई लाइन, कोई चेक, खोज, या प्रदर्शित नहीं)। स्ट्रिंग के लिए एक विशाल स्थान को पूर्व-आरक्षित करने से भी मदद नहीं मिली।
लगता है कि गेटलाइन पूरी तरह से चालक है। हालांकि ... अगर मैं/ओ 2 ध्वज (एमएसवीसी ++) के साथ संकलित करता हूं तो मुझे कॉमिक रूप से तेज़ 26 सेकंड मिलते हैं। इसके अलावा, लंबी लाइनों बनाम कम पर कोई स्पष्ट धीमा नहीं है। स्पष्ट रूप से संकलक कुछ अलग कर रहा है। मुझसे कोई शिकायत नहीं, लेकिन किसी भी विचार के रूप में यह कैसे हासिल किया जाता है? एक अभ्यास के रूप में मैं संकलक अनुकूलन से पहले तेजी से निष्पादित करने के लिए कोशिश करना चाहता हूं और अपना कोड प्राप्त करना चाहता हूं।
मुझे यकीन है कि गेटलाइन स्ट्रिंग में हेरफेर करने के तरीके से कुछ करना है। स्ट्रिंग के लिए पूरी फाइलसाइज को आरक्षित करने के लिए यह तेजी से होगा (या थोड़ी देर के लिए परीक्षण नहीं कर सकता), और चरित्र द्वारा वर्ण पढ़ते हैं, जब मैं/n पास करता हूं तो मेरी लाइन संख्या में वृद्धि करता है? साथ ही, क्या कंपाइलर एमएमएपी जैसी चीजें नियोजित करेगा?
अपडेट: मैं इस शाम को घर आने पर कोड पोस्ट करूंगा। ऐसा लगता है कि रनटाइम चेक बंद करने से 400 सेकंड से 50 तक निष्पादन गिरा दिया गया है! मैंने कच्चे सी स्टाइल सरणी का उपयोग करके एक ही कार्यक्षमता करने की कोशिश की। मैं सुपर अनुभवी नहीं हूं, लेकिन डेटा को एक वर्ण सरणी में डंप करने के लिए काफी आसान था, और इसके माध्यम से लूप न्यूलाइन या मेरी लक्ष्य स्ट्रिंग के पहले अक्षर की तलाश में था।
यहां तक कि पूर्ण डीबग मोड में भी यह अंत तक पहुंच जाता है और 54 सेकंड में स्ट्रिंग को सही तरीके से पाता है। चेक के साथ 26 सेकंड, और 20 सेकंड अनुकूलित। तो मेरे अनौपचारिक, विज्ञापन-प्रसार प्रयोगों से ऐसा लगता है कि स्ट्रिंग और स्ट्रीम फ़ंक्शंस रनटाइम चेक द्वारा पीड़ित हैं? फिर, जब मैं घर जाता हूं तो मैं दोबारा जांच करूंगा।
सी ++ तेज़ है, यो। – Barry
आप केवल 'std :: cout << lineNum << std :: endl;'। जो आपको कुछ समय बचा सकता है। – Lingxi
यह पहली बार होना चाहिए जब मैं किसी को iostreams "तेज़" कहता हूं। संभावनाओं में डीबग चेक छोड़ना शामिल है (एमएसवीसी की मानक पुस्तकालय में उनमें से बहुत सारे हैं), बेहतर इनलाइनिंग, devirtualization। –