2012-01-13 30 views
114

के प्रत्येक मान को रीसेट करने का सबसे तेज़ तरीका std::vector<int> से 0 के प्रत्येक मान को रीसेट करने और वैक्टर प्रारंभिक आकार को रखने का सबसे तेज़ तरीका क्या है?std :: vector <int> से 0

ए [] ऑपरेटर के साथ लूप के लिए?

+3

[std :: भरने] (http://www.cplusplus.com/reference/algorithm/fill/) –

+0

"सर्वाधिक" प्रदर्शन में के रूप में? या लागू करने/बनाए रखने के लिए सबसे आसान में? – TheGeneral

उत्तर

218
std::fill(v.begin(), v.end(), 0); 
+30

असेंबली आउटपुट को देखते हुए, जीसीसी वास्तव में एमएमएक्स रजिस्टरों का उपयोग करने में इस लूप को 16 बाइट्स में डंप करने के लिए अनलॉक करता है जब तक कि यह अंत तक न हो जाए। मैं कहूंगा कि यह बहुत तेज़ है। मेमसेट संस्करण मेमसेट करने के लिए कूदता है, जिसे मैं अनुमान लगा रहा हूं उतना तेज़ है। मैं आपकी विधि का उपयोग करूंगा। – Omnifarious

+0

लेकिन, मेमसेट पर कूदना एक ही निर्देश है, इसलिए इसका उपयोग करने से एक छोटा बाइनरी आकार होगा। –

+0

यह वही नहीं है जो ओपी ने पूछा था, लेकिन अपने वेक्टर को उसी आकार के एक नए आकार में फिर से सौंपना ('v = std :: vector (vec_size, 0)') मेरी मशीन –

12

यदि यह महज पूर्णांकों का एक वेक्टर है, मैं पहले की कोशिश करेंगे:

memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]); 

यह बहुत सी ++ नहीं है, तो मुझे यकीन है कि किसी को ऐसा करने का उचित तरीके से प्रदान करेगा हूँ। :)

+2

मानक (2003 टीसी 1) गारंटी देता है कि एक std :: वेक्टर स्मृति में संगत है, यह ठीक होना चाहिए। यदि आपकी सी ++ लाइब्रेरी 2003 टीसी 1 के अनुरूप नहीं है, तो इसका उपयोग न करें। – Mario

+2

@ मारियो: मैं इसे तब तक पोस्ट नहीं करता जब तक वह सच नहीं था और निश्चित रूप से जाना जाता था। :) लेकिन धन्यवाद। – unwind

+1

मैंने असेंबली की जांच की। ':: std :: fill' विधि कुछ ऐसी चीज तक फैली हुई है जो बहुत तेज है, हालांकि कोड-ब्लोटी पक्ष पर थोड़ा सा है क्योंकि यह सभी इनलाइन है। मैं अभी भी इसका उपयोग करूँगा हालांकि यह पढ़ने के लिए बहुत अच्छा है। – Omnifarious

2

std::fill 

कोशिश करते हैं और यह भी

std::size siz = vec.size(); 
//no memory allocating 
vec.resize(0); 
vec.resize(siz, 0); 
+0

आकार से धीमा होने से बहुत अच्छा – Nick

109

हमेशा की तरह जब आप से पूछना के बारे में सबसे तेजी से: उपाय! (Mac पर बजना का उपयोग) उपरोक्त विधि का प्रयोग:

Method  | executable size | Time Taken (in sec) | 
      | -O0 | -O3 | -O0  | -O3  | 
------------|---------|---------|-----------|----------| 
1. memset | 17 kB | 8.6 kB | 0.125  | 0.124 | 
2. fill  | 19 kB | 8.6 kB | 13.4  | 0.124 | 
3. manual | 19 kB | 8.6 kB | 14.5  | 0.124 | 
4. assign | 24 kB | 9.0 kB | 1.9  | 0.591 | 

10000 ints का एक वेक्टर पर 100000 पुनरावृत्तियों का उपयोग कर।

संपादित करें: इस संख्या अनुग्राह्यतापूर्वक changeing बदल जाता है जिसके परिणामस्वरूप बार यदि आप कुछ विश्वास (अंतिम विधानसभा कोड निरीक्षण के रूप में के रूप में अच्छा नहीं) है कि कृत्रिम बेंचमार्क पूरी तरह से दूर अनुकूलित नहीं किया गया है हो सकता है। बेशक वास्तविक परिस्थितियों में प्रदर्शन को खराब करना सबसे अच्छा है। अंत संपादित

संदर्भ के लिए इस्तेमाल किया कोड:

#include <vector> 

#define TEST_METHOD 1 
const size_t TEST_ITERATIONS = 100000; 
const size_t TEST_ARRAY_SIZE = 10000; 

int main(int argc, char** argv) { 

    std::vector<int> v(TEST_ARRAY_SIZE, 0); 

    for(size_t i = 0; i < TEST_ITERATIONS; ++i) { 
    #if TEST_METHOD == 1 
     memset(&v[0], 0, v.size() * sizeof v[0]); 
    #elif TEST_METHOD == 2 
     std::fill(v.begin(), v.end(), 0); 
    #elif TEST_METHOD == 3 
     for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) { 
     *it = 0; 
     } 
    #elif TEST_METHOD == 4 
     v.assign(v.size(),0); 
    #endif 
    } 

    return EXIT_SUCCESS; 
} 

निष्कर्ष: उपयोग std::fill (क्योंकि, जैसा कि दूसरों इसकी सबसे मुहावरेदार ने कहा है)!

+2

+1 है। यह विशेष बेंचमार्क निर्णायक नहीं है, लेकिन बिंदु बिल्कुल सही है, आपको विकल्पों का प्रदर्शन परीक्षण लिखना चाहिए क्योंकि वास्तव में उनका उपयोग किया जाएगा। यदि कोई प्रदर्शन अंतर नहीं है तो सबसे सरल स्रोत का उपयोग करें। –

+1

"... निर्णायक नहीं है ..." आईएमओ स्वयं में यह अनिवार्यता पहले से ही बेंचमार्क करने के लिए एक अच्छी बात है, ओपीओ के बारे में पूछे जाने वाले स्थितियों के लिए ऑप्टिमाइज़र पहले से ही बहुत अच्छा काम नहीं करता है। और मैं आपके अंतिम वाक्य को पढ़ने के लिए संशोधित करूंगा "यदि कोई ** महत्वपूर्ण ** प्रदर्शन अंतर नहीं है ..." –

+1

"निर्णायक नहीं" से मेरा मतलब था कि सिर्फ इसलिए कि वे इस कार्यक्रम में एक ही गति थे, इसका मतलब यह नहीं है वे सभी प्रश्नकर्ता के कार्यक्रम में एक ही गति होगी। किसी और चीज के अलावा, आपको यह सुनिश्चित करने की आवश्यकता होगी कि स्मृति वास्तव में शून्य थी - यह अनुकूलक परीक्षण को धोखा देने के लिए पर्याप्त स्मार्ट था। लेकिन चूंकि आपके पास प्रश्नकर्ता का कार्यक्रम नहीं है, यह इस उत्तर में विफल नहीं है :-) और आप बिल्कुल सही हैं, किसी विकल्प पर परेशान करने में समय बिताना बहुत आसान है जो वास्तव में कोई फर्क नहीं पड़ता (या एक महत्वहीन अंतर) एक बार अनुकूलित। –

18

assign सदस्य फ़ंक्शन के बारे में कैसे?

some_vector.assign(some_vector.size(), 0); 
+0

ओपी मौजूदा मानों को रीसेट करना चाहता था, लेकिन मानों को रीसेट करने के लिए _and_ आकार बदलने के लिए आपका उत्तर बेहतर है। धन्यवाद! –

0

मैं एक ही सवाल है, लेकिन के बारे में नहीं बल्कि कम vector<bool> (afaik मानक बूलियन तत्वों का सिर्फ एक निरंतर सरणी से आंतरिक रूप से अलग ढंग से इसे लागू करने के लिए अनुमति देता है) था। इसलिए मैंने फैबियो फ्रैकासी द्वारा थोड़ा संशोधित परीक्षण दोहराया। परिणाम (बार, सेकंड में) इस प्रकार हैं:

  -O0  -O3 
     -------- -------- 
memset  0.666  1.045 
fill  19.357  1.066 
iterator 67.368  1.043 
assign 17.975  0.530 
for i  22.610  1.004 
इन आकार के लिए

तो जाहिरा तौर पर, vector<bool>::assign() तेज है। परीक्षण के लिए इस्तेमाल किया कोड:

#include <vector> 
#include <cstring> 
#include <cstdlib> 

#define TEST_METHOD 5 
const size_t TEST_ITERATIONS = 34359738; 
const size_t TEST_ARRAY_SIZE = 200; 

using namespace std; 

int main(int argc, char** argv) { 

    std::vector<int> v(TEST_ARRAY_SIZE, 0); 

    for(size_t i = 0; i < TEST_ITERATIONS; ++i) { 
#if TEST_METHOD == 1 
     memset(&v[0], false, v.size() * sizeof v[0]); 
#elif TEST_METHOD == 2 
     std::fill(v.begin(), v.end(), false); 
    #elif TEST_METHOD == 3 
     for (std::vector<int>::iterator it=v.begin(), end=v.end(); it!=end; ++it) { 
      *it = 0; 
     } 
    #elif TEST_METHOD == 4 
     v.assign(v.size(),false); 
    #elif TEST_METHOD == 5 
     for (size_t i = 0; i < TEST_ARRAY_SIZE; i++) { 
      v[i] = false; 
     } 
#endif 
    } 

    return EXIT_SUCCESS; 
} 

मैं उबंटू 17.10 पर जीसीसी 7.2.0 संकलक इस्तेमाल किया। संकलन के लिए आदेश पंक्ति:

g++ -std=c++11 -O0 main.cpp 
g++ -std=c++11 -O3 main.cpp 
संबंधित मुद्दे