2009-07-29 11 views
43

के लिए ... निम्न मान लिया जाये कि
आउटपुट:
फ़ाइल खोला है ...
डाटा है डिस्क के लिए 'स्ट्रीम किया'। स्मृति में डेटा एक बड़े संगत बफर में है। यह सीधे उस बफर से अपने कच्चे रूप में डिस्क पर लिखा जाता है। बफर का आकार कॉन्फ़िगर करने योग्य है, लेकिन स्ट्रीम की अवधि के लिए तय किया गया है। बफर फाइल पर लिखे जाते हैं, एक दूसरे के बाद। कोई तलाश संचालन नहीं किया जाता है।
... फ़ाइल बंद है।सी ++ में उच्च प्रदर्शन अनुक्रमिक फ़ाइल I/O के लिए सबसे तेज़ तरीका क्या है?

इनपुट:
एक बड़ी फ़ाइल (क्रमिक रूप से जैसा कि ऊपर लिखा जाता है) शुरू से अंत तक से डिस्क से पढ़ा जाता है।


क्या सी ++ में सबसे तेज़ संभव अनुक्रमिक फ़ाइल I/O प्राप्त करने के लिए आम तौर पर दिशानिर्देश स्वीकार किए जाते हैं?

कुछ संभव विचार:

  • दिशानिर्देश इष्टतम बफर आकार को चुनने के लिए
  • बढ़ावा तरह एक पोर्टेबल पुस्तकालय :: asio वे माना जा सकता है भी एक विशिष्ट मंच की पेचीदगियों को बेनकाब करने के लिए निकाला जा सकता है या होगा इष्टतम होने के लिए?
  • असिंक्रोनस I/O हमेशा तुल्यकालिक के लिए बेहतर है? क्या होगा यदि एप्लिकेशन अन्यथा सीपीयू-बाध्य नहीं है?

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

+0

क्या आप 'सीपी' को फिर से लागू करना चाहते हैं? मुझे लगता है कि मुझे कुछ याद आ रहा है ... –

उत्तर

29

क्या सी ++ में सबसे तेज़ संभव अनुक्रमिक फ़ाइल I/O प्राप्त करने के लिए आम तौर पर दिशानिर्देश स्वीकार किए जाते हैं?

नियम 0: उपाय। सभी उपलब्ध प्रोफाइलिंग टूल का उपयोग करें और उन्हें जानें। यह प्रोग्रामिंग में लगभग एक आदेश है कि यदि आपने इसे माप नहीं लिया है तो आप नहीं जानते कि यह कितनी तेज़ है, और I/O के लिए यह और भी सत्य है। यदि आप संभवतः वास्तविक कार्य परिस्थितियों के तहत परीक्षण करना सुनिश्चित करें। एक प्रक्रिया जिसमें I/O सिस्टम के लिए कोई प्रतिस्पर्धा नहीं है, को वास्तविक लोड के तहत मौजूद स्थितियों के लिए ठीक-ठीक किया जा सकता है।

  1. फ़ाइलों को लिखने के बजाय मैप मेमोरी का उपयोग करें। यह हमेशा तेज़ नहीं होता है, लेकिन यह अनावश्यक प्रतिलिपि से बचकर, ओएस के ज्ञान का लाभ उठाते हुए डिस्क को वास्तव में कैसे उपयोग किया जा रहा है, इसका लाभ लेते हुए ऑपरेटिंग सिस्टम-विशिष्ट लेकिन अपेक्षाकृत पोर्टेबल तरीके से I/O को अनुकूलित करने का अवसर प्रदान करता है। ("पोर्टेबल" यदि आप एक रैपर का उपयोग करते हैं, ओएस-विशिष्ट एपीआई कॉल नहीं)।

  2. जितना संभव हो सके अपने आउटपुट को आज़माएं और रैखिक करें। बफर लिखने के लिए स्मृति के चारों ओर कूदने के लिए अनुकूलित स्थितियों के तहत ध्यान देने योग्य प्रभाव हो सकते हैं, क्योंकि कैश लाइन, पेजिंग और अन्य मेमोरी उपप्रणाली के मुद्दों पर कोई फर्क नहीं पड़ता। यदि आपके पास स्कैटर-इकट्ठा I/O के लिए बहुत सारे बफर समर्थन में हैं जो आपके लिए रैखिकरण करने का प्रयास करता है।

कुछ संभव विचार:

  • दिशानिर्देश शुरुआत के लिए इष्टतम बफर आकार

पृष्ठ आकार को चुनने के लिए, लेकिन वहाँ से धुन के लिए तैयार हो।

  • बढ़ावा तरह एक पोर्टेबल पुस्तकालय :: asio भी पेचीदगियों एक विशिष्ट मंच के बेनकाब करने के लिए निकाला जाएगा, या वे इष्टतम माना जा सकता है?

यह इष्टतम मानें मत। यह इस बात पर निर्भर करता है कि लाइब्रेरी आपके प्लेटफॉर्म पर कितनी अच्छी तरह से प्रयोग की जाती है, और डेवलपर्स ने इसे तेजी से बनाने में कितना प्रयास किया।यह कहकर कि एक पोर्टेबल I/O लाइब्रेरी बहुत तेज़ हो सकता है, क्योंकि अधिकांश प्रणालियों पर तेज़ अवशोषण मौजूद होते हैं, और आमतौर पर सामान्य एपीआई के साथ आना संभव होता है जिसमें बहुत से आधार शामिल होते हैं। Boost.Asio, मेरे सीमित ज्ञान के लिए सबसे अच्छा है, यह विशेष मंच के लिए काफी ठीक है: यह तेजी से एसिंक I/O (जैसे epoll, /dev/epoll, kqueue के लिए ओएस और ओएस-वेरिएंट विशिष्ट एपीआई का पूरा परिवार है, Windows overlapped I/O), और एशियाओ उन सभी को लपेटता है।

  • अतुल्यकालिक मैं/हे हमेशा बेहतर तुल्यकालिक है? क्या होगा यदि एप्लिकेशन अन्यथा सीपीयू-बाध्य नहीं है?

अतुल्यकालिक मैं/हे तेजी से तुल्यकालिक आई/ओ एक कच्चे अर्थ में नहीं है। एसिंक्रोनस I/O क्या सुनिश्चित करता है कि आपके कोड I/O को पूरा करने के लिए समय बर्बाद नहीं कर रहा है। यह उस समय को बर्बाद न करने की दूसरी विधि की तुलना में एक सामान्य तरीके से तेज़ है, अर्थात् थ्रेड का उपयोग करना, क्योंकि यह आपके कोड में वापस कॉल करेगा जब मैं/ओ तैयार हो और पहले नहीं। निष्क्रिय धागे को समाप्त करने की आवश्यकता के साथ कोई झूठी शुरुआत या चिंता नहीं है।

+1

उत्कृष्ट उत्तर – user394460

3

आप बताया गया है ऊपर यह सब मशीन/system/पुस्तकालयों है कि आप प्रयोग कर रहे हैं पर निर्भर करता है। एक प्रणाली पर एक तेज समाधान दूसरे पर धीमा हो सकता है।

हालांकि एक सामान्य दिशानिर्देश जितना संभव हो उतना बड़ा हिस्सा लिखना होगा।
आमतौर पर एक समय में एक बाइट लिखना सबसे धीमा है।

निश्चित रूप से जानने के लिए सबसे अच्छा तरीका कुछ अलग तरीकों को कोड करना और उन्हें प्रोफ़ाइल करना है।

+0

+1 माप के लिए पहले! –

5

विंडोज के लिए, आप यह सुनिश्चित करना चाहते हैं कि आप अपने CreateFile() कॉल में FILE_FLAG_SEQUENTIAL_SCAN का उपयोग करें, यदि आप प्लेटफार्म विशिष्ट विंडोज एपीआई कॉल का उपयोग करने का विकल्प चुनते हैं। यह आई/ओ के लिए कैशिंग अनुकूलित करेगा। जहां तक ​​बफर आकार जाते हैं, डिस्क क्षेत्र के आकार के एक बफर आकार का आमतौर पर सलाह दी जाती है। 8K एक अच्छा प्रारंभिक बिंदु है जिसमें छोटे से जाने से कम प्राप्त किया जा सकता है।

यह आलेख विंडोज पर एसिंक और सिंक के बीच तुलना की चर्चा करता है।

http://msdn.microsoft.com/en-us/library/aa365683(VS.85).aspx

10

एक सामान्य सलाह बफरिंग बंद कर देते हैं और जहां अन्यथा आप कर सकते थे पूरा करने के लिए पढ़ने के बड़े हिस्से में/लिखने (लेकिन बहुत बड़ी है, तो आप बहुत अधिक समय पूरे मैं के लिए इंतज़ार कर बर्बाद करेंगे/ओ करने के लिए है पहले मेगाबाइट पर पहले से ही घुमाएं। इस एल्गोरिदम के साथ मीठा स्थान ढूंढना मुश्किल है, केवल एक घुंडी चालू करने के लिए है: खंड आकार)।

इसके अलावा, mmap() इनपुट फ़ाइल के लिए इनपुट और केवल पढ़ने के लिए (यदि सबसे तेज़ नहीं है, तो सबसे प्रभावी तरीका है)। madvise() पर कॉल करें यदि आपके प्लेटफ़ॉर्म में यह है कि कर्नेल को यह बताने के लिए कि आप फ़ाइल को कैसे पार करेंगे, तो यह रीडहेड कर सकता है और पृष्ठों को बाद में तुरंत फेंक सकता है।

आउटपुट के लिए, यदि आपके पास पहले से ही बफर है, तो इसे फ़ाइल के साथ अंडरपिन करने पर विचार करें (mmap() के साथ), इसलिए आपको डेटा स्पेस में डेटा कॉपी करने की आवश्यकता नहीं है।

यदि mmap() आपकी पसंद के हिसाब से नहीं है, तो fadvise() है, और, वास्तव में कठिन लोगों के लिए, async फ़ाइल I/O।

(उपर्युक्त सभी POSIX है, विंडोज नाम अलग हो सकते हैं)।

+1

फिक्स: फ़ैडवाइस (2) और पागलपन (2)। इसके अलावा पॉज़िक्स संस्करणों का नाम posix_fadvise और posix_madvise – osgx

2

आपने सी ++ के बारे में पूछा, लेकिन ऐसा लगता है कि आप पिछले हैं और थोड़ा सा मंच-विशिष्ट प्राप्त करने के लिए तैयार हैं।

विंडोज़ पर, FILE_FLAG_SEQUENTIAL_SCAN फ़ाइल मैपिंग के साथ शायद सबसे तेज़ तरीका है। वास्तव में, फाइल वास्तव में डिस्क पर इसे बनाने से पहले आपकी प्रक्रिया से बाहर निकल सकती है। एक स्पष्ट रूप से अवरुद्ध फ्लश ऑपरेशन के बिना, विंडोज़ उन पृष्ठों को लिखना शुरू करने में 5 मिनट तक लग सकते हैं।

यदि फाइलें स्थानीय डिवाइस पर नहीं हैं लेकिन नेटवर्क ड्राइव पर हैं तो आपको सावधान रहना होगा। नेटवर्क त्रुटियां एसईएच त्रुटियों के रूप में दिखाई देंगी, जिन्हें आपको संभालने के लिए तैयार होने की आवश्यकता होगी।

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

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

+1

पॉज़िक्स में POSIX_FADV_SEQUENTIAL ध्वज के साथ संगत posix_fadvise कॉल है। – osgx

2

आपको CreateFile और ReadFile का उपयोग कर पूर्ण तेज़ प्रदर्शन प्राप्त होगा। FILE_FLAG_SEQUENTIAL_SCAN के साथ फ़ाइल खोलें।

एक बफर आकार के साथ पढ़ें जो दो की शक्ति है। केवल बेंचमार्किंग ही इस नंबर को निर्धारित कर सकती है। मैंने इसे एक बार 8 के रूप में देखा है। एक और बार मैंने इसे 8 एम पाया! यह जंगली ढंग से बदलता है।

यह सीपीयू कैश के आकार पर निर्भर करता है, ओएस पढ़ने की क्षमता पर और कई छोटे लिखने से जुड़े ओवरहेड पर निर्भर करता है।

मेमोरी मैपिंग सबसे तेज़ तरीका नहीं है। इसमें अधिक ओवरहेड है क्योंकि आप ब्लॉक आकार को नियंत्रित नहीं कर सकते हैं और ओएस को सभी पृष्ठों में गलती की आवश्यकता है।

1

लिनक्स पर, बफ़र पढ़ता है और एक बहुत चीज़ों को गति, तेजी से बफ़र आकार में वृद्धि के साथ लिखते हैं, लेकिन रिटर्न ह्रासमान रहे हैं और आप आम तौर पर BUFSIZ बड़ा बफर आकार के रूप में (stdio.h द्वारा परिभाषित) का उपयोग करने के लिए बहुत मदद नहीं करेगा चाहते हैं ।

mmap आईएनजी फ़ाइलों तक सबसे तेज़ पहुंच प्रदान करता है, लेकिन mmap कॉल स्वयं ही महंगा है। छोटी फ़ाइलों (16KiB) read और write सिस्टम कॉल जीतने के लिए (https://stackoverflow.com/a/39196499/1084774read और mmap के माध्यम से पढ़ने पर संख्याओं के लिए देखें)।

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