Який найшвидший спосіб скинути кожне значення a std::vector<int>
до 0 і зберегти початковий розмір векторів?
A для циклу з оператором []?
Який найшвидший спосіб скинути кожне значення a std::vector<int>
до 0 і зберегти початковий розмір векторів?
A для циклу з оператором []?
Відповіді:
std::fill(v.begin(), v.end(), 0);
v = std::vector<int>(vec_size,0)
) здається трохи швидшим, ніж fill
на моїй машині
assign
.
Як завжди, коли ви запитуєте про найшвидший: Міряйте! Використовуючи вищезазначені методи (на 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 ints.
Редагувати: Якщо зміна цих цифр правдоподібно змінить отримані часи, ви можете мати певну впевненість (не так добре, як перевірка остаточного коду збірки), що штучний показник не був повністю оптимізований. Звичайно, найкраще зіпсувати виступ у реальних умовах. завершити Редагувати
для довідки використаний код:
#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
(бо, як інші сказали, це саме ідіоматичне)!
assign
повільніше, за винятком невеликих потужностей на libc++
. КОД coliru / paste
fill
виглядає жахливо. Це на два порядки повільніше в цьому тесті.
Як щодо функції assign
члена?
some_vector.assign(some_vector.size(), 0);
Якщо це просто вектор цілих чисел, я спершу спробую:
memset(&my_vector[0], 0, my_vector.size() * sizeof my_vector[0]);
Це не дуже C ++, тому я впевнений, що хтось забезпечить правильний спосіб цього. :)
::std::fill
Метод розширюється до чого - то , що це чертовски швидко, хоча і трохи по кодовою bloaty стороні , так як це все інлайн. Я б все одно користувався цим, хоча читати набагато приємніше.
У мене було те саме питання, але щодо досить короткого 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