C ++ - STL векторный вопрос - PullRequest
3 голосов
/ 23 июня 2010

Есть ли способ сделать std::vector быстрее на reserving + resizing?

Я бы хотел добиться производительности, которая была бы несколько эквивалентна простым массивам C.

См. Следующие фрагменты кода:

TEST(test, vector1) {
   for (int i = 0; i < 50; ++i) {
      std::vector<int> a;
      a.reserve(10000000);
      a.resize(10000000);
   }
}

TEST(test, vector2) {
   for (int i = 0; i < 50; ++i) {
      std::vector<int> a(10000000);
   }
}

TEST(test, carray) {
   for (int i = 0; i < 50; ++i) {
      int* new_a = new int[10000000];
      delete[] new_a;
   }
}

Первые два теста в два раза медленнее (4095 ms vs 2101 ms), и, очевидно, это происходит потому, что std::vector обнуляет элементы в нем. Есть идеи, как этого можно избежать?

Или, возможно, существует какой-то стандартный (boost?) контейнер, который реализует массив фиксированного размера и кучи?

Спасибо

Ответы [ 5 ]

11 голосов
/ 23 июня 2010

Ну, естественно, первые 2 теста медленнее.Они явно проходят через весь вектор и вызывают "int ()" для каждого элемента.Редактировать: Это дает эффект установки всех элементов на «0».

Просто попробуйте зарезервировать.

В этом вопросе есть очень важная информация для вашего вопроса, который я задал некоторое время назад:

std :: vector reserve () и push_back () быстрее, чем resize () и индекс массива, почему?

2 голосов
/ 23 июня 2010

Были ли ваши тесты выполнены в режиме отладки или выпуска? Я знаю, что компилятор Microsoft добавляет множество проверок отладки, которые действительно могут снизить производительность.

2 голосов
/ 23 июня 2010
1 голос
/ 24 июня 2010

Я собираюсь дать вам преимущество сомнения и предположить, что вы уже выполнили какое-то профилирование и определили использование вектора таким образом, чтобы быть горячей точкой. Если нет, то немного преждевременно учитывать различия, если только вы не работаете над очень узким, мелкомасштабным приложением, в котором учитывается каждый тактовый цикл, и в этом случае еще проще использовать профилировщик, и для этого есть такая же причина поэтому.

boost :: scoped_array - одно из решений. Нет способа получить вектор, чтобы не инициализировать элементы, которые он хранит. Другой - std :: deque, если вам не нужен непрерывный блок памяти. deque может быть значительно быстрее, чем vector или динамически распределяемый массив с тем же числом элементов, что и при создании, так как он создает меньшие блоки памяти, с которыми операционные системы имеют тенденцию работать лучше, а также кеша.

1 голос
/ 23 июня 2010

Может быть, вы могли бы использовать boost :: scoped_array , но если это действительно критично для производительности, возможно, вам следует как-то попытаться поместить инициализацию / распределение вне самого внутреннего цикла?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...