স্ট্যান্ড :: ভেক্টর <মান> এর প্রতিটি মান পুনরায় সেট করার দ্রুততম উপায়


198

এক std::vector<int>থেকে 0 এর প্রতিটি মান পুনরায় সেট করার এবং ভেক্টরদের প্রাথমিক আকার রাখার দ্রুততম উপায় কী ?

[]] অপারেটরের সাথে লুপের জন্য?



1
অভিনয় হিসাবে "দ্রুততম"? অথবা কার্যকর / বজায় রাখা সবচেয়ে সহজ হিসাবে?
জেনারাল

উত্তর:


340
std::fill(v.begin(), v.end(), 0);

48
সমাবেশের আউটপুটটি দেখে, জিসিসি প্রকৃতপক্ষে এই লুপটি এমআলএমএক্স রেজিস্টারগুলিকে একবারে 16 বাইটে ডাম্প করার জন্য শেষের দিকে না আসা পর্যন্ত ব্যবহার করে তালিকাভুক্ত করে। আমি বলি যে এটি খুব দ্রুত। মেমসেট সংস্করণটি মেমসেটে লাফিয়ে যায়, যা আমি অনুমান করছি প্রায় দ্রুত। আমি আপনার পদ্ধতি ব্যবহার করব
সর্বজনীন

তবে, মেমসেটে জাম্পিং একটি একক নির্দেশনা, সুতরাং এটি ব্যবহারের ফলে একটি ছোট বাইনারি আকারের ফলস্বরূপ।
আলেকজান্ডার শিশেঙ্কো

2
এটি ওপি যা বলেছিল ঠিক তেমন নয়, তবে কেবল একই মাপের নতুনটিকে আপনার ভেক্টরকে পুনরায় নিয়োগ করা ( v = std::vector<int>(vec_size,0)) fillআমার মেশিনের চেয়ে কিছুটা দ্রুত বলে মনে হচ্ছে
ইয়েবো ইয়াং

1
এটি এটি করার সবচেয়ে মূর্তিমান পদ্ধতি, ব্যবহারের চেয়ে বেশি মূর্তিমানিক assign
alfC

1
এটি কোনও নতুন ভেক্টরকে বরাদ্দ করে হিপ বরাদ্দ দেয় না? এবং তারপরে বিদ্যমান ভেক্টরের বরাদ্দটি বাতিল করবেন? আমি দেখতে পেলাম মেমসেট এট আলের চেয়ে ধীর হচ্ছে
কনরাড জোন্স

150

সর্বদা হিসাবে যখন আপনি দ্রুততম সম্পর্কে জিজ্ঞাসা করেন: পরিমাপ করুন! উপরের পদ্ধতিগুলি (কলঙ্ক ব্যবহার করে ম্যাকে) ব্যবহার করে:

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 পুনরাবৃত্তি ব্যবহার করে।

সম্পাদনা করুন: যদি এই সংখ্যাগুলি পরিবর্তন করে ফলস্বরূপ পরিবর্তিত ফলাফলগুলি আপনি কিছুটা আস্থা রাখতে পারেন (চূড়ান্ত সমাবেশ কোডটি পরিদর্শন করার মতো ভাল নয়) যে কৃত্রিম বেঞ্চমার্ক পুরোপুরি অপ্টিমাইজড হয়নি। অবশ্যই বাস্তব অবস্থার অধীনে পারফরম্যান্সকে গোলমাল করা ভাল। শেষ সম্পাদনা

রেফারেন্সের জন্য ব্যবহৃত কোড:

#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(কারণ, অন্যরা যেমন এর সবচেয়ে মূর্তিমান বলেছেন)!


3
+1 টি। এই নির্দিষ্ট মাপদণ্ডটি চূড়ান্ত নয়, তবে বিষয়টি একেবারে সঠিক, আপনার বিকল্পগুলির কার্যকারিতা পরীক্ষাটি লিখতে হবে কারণ সেগুলি বাস্তবে ব্যবহৃত হবে। যদি কোনও পারফরম্যান্সের পার্থক্য না থাকে তবে সবচেয়ে সহজ উত্স যেটি ব্যবহার করুন।
স্টিভ জেসোপ

3
"... চূড়ান্ত নয় ..." আইপিও নিজের মধ্যে এই অসম্পূর্ণতা ইতিমধ্যে বেঞ্চমার্কগুলি করার জন্য একটি ভাল পয়েন্ট, প্রায়শই অপ্টিমাইজার ইতিমধ্যে ওপি যে ধরনের পরিস্থিতি সম্পর্কে জিজ্ঞাসা করেছিল তার জন্য খুব ভাল কাজ করে না। এবং "আপনার যদি পারফরম্যান্সের কোনও উল্লেখযোগ্য পার্থক্য না হয় ..." পড়তে আপনার শেষ বাক্যটি পরিবর্তন করে
ফেলতাম

4
আপডেট ব্যবহার Nonius benchmarks জন্য: clang3.6-libc ++, - C ++ 1 বর্ষ-হয় O3 , gcc4.9-C ++ 1 বর্ষ-হয় O3 এবং gcc5-C ++ 1 বর্ষ-হয় O3 - টি এল; ডিআর : assign, ধীর ছোট ক্ষমতা ছাড়া উপর libc++। CODE কলিরু / পেস্ট
সেপ্টেম্বর

2
এছাড়াও, বাহ, আপনি অপটিমাইজেশন ছাড়াই গতি সম্পর্কে চিন্তা করেন (যা আপনি 'ডিবাগ' মোডে স্থাপন করছেন, যদি কিছু দল এটি করে তবে এটি প্রশংসনীয় হতে পারে) fillভয়ঙ্কর দেখাচ্ছে। এটি এই পরীক্ষায় ধীর গতির দুটি অর্ডার
কাইল স্ট্র্যান্ড

5
@ কাইলস্ট্র্যান্ড: এটি ভরাট ভয়াবহ নয়, এটি একটি টেম্পলেট এবং কোডটি আপনার অনুবাদ ইউনিটের ভিতরে -O0 দিয়ে তৈরি করা হয়েছে। আপনি যখন মেমসেট ব্যবহার করেন, আপনি libc কোডটি ব্যবহার করেন যা -O3 দিয়ে সংকলিত হয়েছিল (এমনকি যখন আপনি আপনার কোড -O0 দিয়ে সংকলন করেন)। আপনি যদি ডিবাগের গতি সম্পর্কে চিন্তা করেন এবং আপনি টেম্পলেটগুলি ব্যবহার করেন তবে আপনাকে আলাদা ফাইলটিতে স্পষ্টভাবে টেম্পলেট ইনস্ট্যান্টেশন ব্যবহার করতে হবে যা আপনি -O3
টিকিট

25

assignসদস্য ফাংশন সম্পর্কে কীভাবে ?

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

2
ওপি বিদ্যমান মানগুলিকে পুনরায় সেট করতে চেয়েছিল তবে মানগুলি পুনরায় আকার দিতে এবং পুনরায় সেট করতে চাইলে আপনার উত্তরটি আরও ভাল । ধন্যবাদ!

15

যদি এটি কেবল পূর্ণসংখ্যার ভেক্টর হয় তবে আমি প্রথমে চেষ্টা করব:

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

এটি খুব বেশি সি ++ নয়, তাই আমি নিশ্চিত যে কেউ এটি করার উপযুক্ত উপায় সরবরাহ করবে। :)


3
যেহেতু স্ট্যান্ডার্ড (২০০৩ টিসি 1) গ্যারান্টি দেয় যে একটি স্ট্যান্ড :: ভেক্টর স্মৃতিতে সুসংগত, তাই এটি ঠিক করা উচিত। যদি আপনার সি ++ লাইব্রেরি 2003 টিসি 1 এর সাথে সামঞ্জস্য না করে তবে এটি ব্যবহার করবেন না।
মারিও

2
@ মারিও: এটি সত্য না হলে এবং অবশ্যই সুপরিচিত হিসাবে ধরে নেওয়া না গেলে আমি এটি পোস্ট করতাম না। :) কিন্তু ধন্যবাদ.
বিনোদন

1
আমি অ্যাসেম্বলি পরীক্ষা করেছিলাম। ::std::fillপদ্ধতি, এমন কিছু বিষয় যা বেশ দ্রুত darned এর বিস্তৃতি যদিও যেহেতু এটি সব ইনলাইন এর কোড-bloaty দিকে একটি বিট। আমি এখনও এটি ব্যবহার করব যদিও এটি পড়ার পক্ষে খুব ভাল।
সর্বজনীন

4
ভেক্টর খালি আছে কিনা এবং এই ক্ষেত্রে কিছুই না করে আপনার চেক যুক্ত করা ভাল। খালি ভেক্টরের জন্য & বুফ [0] গণনা করা এসটিএল কোডটিতে জোর উত্পন্ন করতে পারে।
সের্গেই

4

চেষ্টা

std::fill

এবং যদিও

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

আকার পরিবর্তন খুব সুন্দর
নিক

3

আমার একই প্রশ্ন ছিল তবে সংক্ষিপ্ত সম্পর্কে vector<bool>(আফিক মানক এটি বুলিয়ান উপাদানগুলির একটি ধারাবাহিক অ্যারের চেয়ে অভ্যন্তরীণভাবে আলাদাভাবে প্রয়োগ করতে দেয়)। অতএব আমি ফ্যাবিও ফ্রেসাসি দ্বারা সামান্য পরিবর্তিত পরীক্ষার পুনরাবৃত্তি করেছি। ফলাফলগুলি নিম্নরূপ (বার, সেকেন্ডে):

            -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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.