2010-06-23 4 views
3

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

Я хотел бы достичь производительности, которая была бы несколько эквивалентна обычным массивам 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?) контейнер, который реализует массив с фиксированным размером и кучей?

Спасибо

+3

Для того, чтобы тесты выполняли одинаковый объем работы, для теста 'carray' требуется значение' for (std :: size_t idx = 0; idx <10000000; ++ idx) new_a [idx] = 0; ' там. Как только это произойдет, я сомневаюсь, что вы найдете значительные изменения. – sbi

+1

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

+1

@Iulian: Это один из тех комментариев, для которых я хочу иметь возможность проголосовать за комментарии. Почему бы вам создать собственный массив?Вы на самом деле пытались реализовать 'std :: vector'? Вы обнаружите, что на удивление трудно придумать, как правильно, так и быстро. – sbi

ответ

11

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

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

Существует несколько весьма актуальной информации, чтобы ваш вопрос в этом вопросе я спросил некоторое время назад:

std::vector reserve() and push_back() is faster than resize() and array index, why?

+0

Правильно, версия «carray» не делает точной * то же, что и векторные счетчики. std :: vector :: reserve() - ответ здесь – rubenvb

2

Там в boost::array.

+0

К сожалению, он основан на стеке, и, например, вы даже не можете выделить огромный массив из 1 миллиона ints без изменения размера стека. –

+0

'std :: auto_ptr >' выполнит эту работу. –

+0

@ HardCoder1986: Если вам нужен массив с кучей, 'std :: vector' - это то, что вы хотите. Исправьте свой тест, и вы увидите, что он точно так же быстро, как ручная работа с динамически распределенными массивами C. – sbi

2

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

1

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

1

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

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