Какой самый быстрый способ сбросить каждое значение std::vector<int>
до 0 и сохранить начальный размер вектора?Самый быстрый способ сбросить каждое значение std :: vector <int> до 0
A для цикла с оператором []?
Какой самый быстрый способ сбросить каждое значение std::vector<int>
до 0 и сохранить начальный размер вектора?Самый быстрый способ сбросить каждое значение std :: vector <int> до 0
A для цикла с оператором []?
std::fill(v.begin(), v.end(), 0);
Глядя на сборку, gcc на самом деле разворачивает этот цикл с использованием регистров mmx для дампа в 16 байт за раз, пока он не приблизится к концу. Я бы сказал, что это довольно быстро. Версия memset переходит к memset, и я предполагаю, что это так же быстро. Я бы использовал ваш метод. – Omnifarious
Но прыжок в memset - это одна команда, поэтому ее использование приведет к меньшему двоичному размеру. –
Это не совсем то, о чем попросил ОП, а просто переназначение вашего вектора на новый один размер ('v = std :: vector
Если это просто вектор целых чисел, я бы первым попробовать:
memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
Это не очень C++, так что я уверен, что кто-то даст правильный способ сделать это. :)
Поскольку стандарт (2003 TC1) гарантирует, что std :: vector смежен в памяти, это должно быть хорошо. Если ваша библиотека C++ не соответствует TC1 2003 года, не используйте это. – Mario
@Mario: Я бы не опубликовал это, если бы это не было правдой и считалось общеизвестным, конечно. :) Но спасибо. – unwind
Я проверил сборку. Метод ':: std :: fill' расширяется до того, что быстро зашифровывается, хотя немного на стороне кода, так как он все встроен. Я все равно буду использовать его, потому что его гораздо приятнее читать. – Omnifarious
попробовать
std::fill
, а также
std::size siz = vec.size();
//no memory allocating
vec.resize(0);
vec.resize(siz, 0);
Изменение размера очень хорошее – Nick
Как всегда, когда вы спрашиваете о быстро: Измерить! Использование методов выше (на Mac с помощью Clang):
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 |
используя 100000 итераций на векторе 10000 Интс.
Edit: Если changeing этого числа правдоподобны изменения результирующие раз вы можете иметь некоторые доверия (не так хорошо, как инспектирование окончательного кода сборки), что искусственный тест не был оптимизирован прочь полностью. Разумеется, лучше справляться с работой в реальных условиях. конец Edit
для справки используемый код:
#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
(потому что, как уже говорили другие его наиболее идиоматических)!
+1. Этот конкретный ориентир не является окончательным, но это абсолютно правильно, вы должны написать тест производительности альтернатив, поскольку они будут фактически использоваться. Если нет разницы в производительности, используйте тот, который является самым простым источником. –
«... не убедительно ...» ИМО эта непоследовательность сама по себе уже является хорошим моментом для выполнения тестов, чаще всего Оптимизатор уже делает очень хорошую работу для тех ситуаций, о которых спрашивал ОП. И я бы изменил ваше последнее предложение следующим образом: «Если нет ** существенной разницы в производительности ...» –
«Неконкретно» Я имел в виду, что только потому, что они были одинаковой скоростью в этой программе, это не обязательно означает все они будут одинаковой скоростью в программе опроса. Помимо всего прочего, вам нужно быть уверенным, что память была фактически обнулена - возможно, оптимизатор был достаточно умен, чтобы обмануть тест. Но так как у вас нет программы опроса, это не провал этого ответа :-) И вы абсолютно правы, очень легко тратить время, мучительно на выбор, который фактически не имеет никакого значения вообще (или незначительная разница) после оптимизации. –
Как насчет функции assign
?
some_vector.assign(some_vector.size(), 0);
OP хотел сбросить существующие значения, но ваш ответ лучше, если вы хотите изменить размер _ и_ сбросить значения. Благодаря! –
У меня был один и тот же вопрос, но о довольно короткий 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;
}
Я использовал GCC 7.2.0 компилятора на Ubuntu 17.10. Командная строка для компиляции:
g++ -std=c++11 -O0 main.cpp
g++ -std=c++11 -O3 main.cpp
[станд :: заливка] (http://www.cplusplus.com/reference/algorithm/fill/) –
"быстрый", как в производительности? Или как проще всего реализовать/поддерживать? – TheGeneral