2009-11-07 18 views
8

का उपयोग करके फ़ाइल करने के लिए बड़े एसटीएल वेक्टर लिखने का सबसे तेज़ तरीका मेरे पास एक बड़े वेक्टर (10^9 तत्व) वर्ण हैं, और मैं सोच रहा था कि इस तरह के वेक्टर को फ़ाइल में लिखने का सबसे तेज़ तरीका क्या है। अब तक मैं अगले कोड का उपयोग किया गया है:एसटीएल

vector<char> vs; 
// ... Fill vector with data 
ofstream outfile("nanocube.txt", ios::out | ios::binary); 
ostream_iterator<char> oi(outfile, '\0'); 
copy(vs.begin(), vs.end(), oi); 

इस कोड को यह लगभग दो मिनट लगते हैं फाइल करने के लिए सभी डेटा लिखने के लिए के लिए। वास्तविक सवाल यह है: "क्या मैं इसे एसटीएल और कैसे उपयोग कर तेजी से बना सकता हूं"?

+0

क्या कोई अन्य प्रसंस्करण कि आप क्या करना चाहते हैं, जबकि लिखने पृष्ठभूमि में होता है? यदि हां, तो उपयोग ओवरलैप मैं/हे बफर और बनाम के रूप में vs.data() गुजरआकार() को चार्ल्स साल्विया द्वारा निर्दिष्ट बाइट्स की संख्या के रूप में लिखा जाना चाहिए। – Modicom

उत्तर

3

ostream_iterator के निर्माता के लिए अपने दूसरे तर्क के साथ एक मामूली वैचारिक त्रुटि है। यह शून्य सूचक हो सकता है अगर आप नहीं चाहते कि एक परिसीमक चाहते हैं (हालांकि, सौभाग्य से आप के लिए, इस तरह के परोक्ष रूप में माना जाएगा), या दूसरा तर्क छोड़ देना चाहिए।

हालांकि, इसका मतलब है कि प्रत्येक चरित्र को लिखने के बाद, कोड को डिलीमीटर (जो कुछ हद तक अक्षम हो सकता है) नामक सूचक के लिए जांच करने की आवश्यकता है।

मुझे लगता है, अगर आप इसे इटरेटर्स के साथ जाना चाहते हैं, तो शायद आप ostreambuf_iterator आज़मा सकते हैं।

अन्य विकल्पों में लेखन() विधि का उपयोग करना शामिल हो सकता है (यदि यह आउटपुट को बड़े पैमाने पर संभाल सकता है, या शायद इसे हिस्सों में आउटपुट कर सकता है), और शायद ओएस-विशिष्ट आउटपुट फ़ंक्शंस।

+1

मैंने मेयर के "प्रभावी एसटीएल" में अनुभाग पढ़ा है जो '[io] streambuf_iterator' वर्गों का उल्लेख करता है। इसके लिए बिल्कुल सही! सुधार के लिए – Tom

+0

Thnx। मैंने गहरा अंतर्दृष्टि के बिना कहीं से पेस्ट कॉपी किया था। – ljubak

+0

मैं यह कहना भूल गया था कि मैं चीजों को प्लेटफ़ॉर्म स्वतंत्र बनाने की कोशिश कर रहा हूं ताकि ओएस विशिष्ट प्रश्न से बाहर हो, लेकिन फिर से thnx। – ljubak

-1

उस पर लिखने की विधि का उपयोग करें, यह रैम में है और आपके पास संक्रामक स्मृति है .. सबसे तेज़, बाद में लचीलापन की तलाश करते समय? बिल्ट-इन बफरिंग, संकेत अनुक्रमिक I/o खोना, इटेटर/उपयोगिता की छिपी चीजें खोना, स्ट्रीमबफ से बचें, लेकिन जब आप बूस्ट :: एएसओ के साथ गंदे हो सकते हैं ..

21

इतनी बड़ी मात्रा में डेटा के साथ लिखा जा (~ 1GB), आप उत्पादन धारा को सीधे नहीं बल्कि एक निर्गम इटरेटर का उपयोग करने से लिखना चाहिए। के बाद से एक सदिश में डेटा समीपवर्ती संग्रहीत किया जाता है, इस काम करेंगे और बहुत तेजी से होना चाहिए।

ofstream outfile("nanocube.txt", ios::out | ios::binary); 
outfile.write(&vs[0], vs.size()); 
+0

मैं सोच रहा था कि 'outfile.write क्यों है (reinterpret_cast (& (बनाम)), vs.size() * sizeof (टी)); 'काम नहीं करता है? – Javier

2

चूंकि आपका डेटा स्मृति में सन्निहित है (के रूप में चार्ल्स ने कहा), तो आप निम्न स्तर आई/ओ उपयोग कर सकते हैं। यूनिक्स या लिनक्स पर, आप एक फ़ाइल डिस्क्रिप्टर को अपना लेखन कर सकते हैं। विंडोज एक्सपी पर, फ़ाइल हैंडल का उपयोग करें। (यह एक्सपी पर थोड़ा सा ट्रिकियर है, लेकिन एमएसडीएन में अच्छी तरह से प्रलेखित है।)

एक्सपी बफरिंग के बारे में थोड़ा मजाकिया है। यदि आप एक संभाल करने के लिए एक 1GB ब्लॉक लिखते हैं, अगर आप (एक पाश में) छोटे हस्तांतरण आकार में लिखने को तोड़ने की तुलना में धीमी हो जाएगा। मैंने पाया है कि 256 केबी लिखने सबसे कुशल हैं। एक बार जब आप पाश में लिखा है, तो आप इस के साथ चारों ओर खेलने के लिए और देखने के सबसे तेजी से स्थानांतरण आकार क्या कर सकते हैं।

1

ठीक है, मैं प्रत्येक यात्रा पर डेटा की पाश कि 256KB ब्लॉक लिखते हैं के लिए के साथ लिखने विधि कार्यान्वयन किया है (जैसा कि रोब सुझाव दिया) और परिणाम 16 सेकंड है, तो समस्या हल हो। यह मेरा विनम्र कार्यान्वयन है इसलिए टिप्पणी करने के लिए स्वतंत्र महसूस करें:

void writeCubeToFile(const vector<char> &vs) 
{ 
    const unsigned int blocksize = 262144; 
    unsigned long blocks = distance(vs.begin(), vs.end())/blocksize; 

    ofstream outfile("nanocube.txt", ios::out | ios::binary); 

    for(unsigned long i = 0; i <= blocks; i++) 
    { 
     unsigned long position = blocksize * i; 

     if(blocksize > distance(vs.begin() + position, vs.end())) outfile.write(&*(vs.begin() + position), distance(vs.begin() + position, vs.end())); 
     else outfile.write(&*(vs.begin() + position), blocksize); 
    } 

    outfile.write("\0", 1); 

    outfile.close(); 
} 

आप सभी को Thnx।

1

आप अन्य संरचना है, तो इस विधि अभी भी मान्य है।

उदाहरण के लिए:

typedef std::pair<int,int> STL_Edge; 
vector<STL_Edge> v; 

void write_file(const char * path){ 
    ofstream outfile(path, ios::out | ios::binary); 
    outfile.write((const char *)&v.front(), v.size()*sizeof(STL_Edge)); 
} 

void read_file(const char * path,int reserveSpaceForEntries){ 
    ifstream infile(path, ios::in | ios::binary); 
    v.resize(reserveSpaceForEntries); 
    infile.read((char *)&v.front(), v.size()*sizeof(STL_Edge)); 
} 
1
इसके बजाय फ़ाइल मैं/हे तरीकों, आप एक स्मृति-मैप की गई फ़ाइल बनाने के लिए memcpy का उपयोग कर स्मृति-मैप की गई फ़ाइल के लिए वेक्टर नकल की कोशिश कर सकते हैं, और फिर के माध्यम से लेखन के