2013-03-27 4 views
1

Я храню и генерирую некоторые данные, которые, естественно, представлены с размером> 1. Однако я видел много ответов, рекомендующих программистам использовать 1D-вектор со своим собственным индексом для представления нескольких измерений. Мой вопрос: что можно получить, используя только 1-мерность?Должен ли я всегда использовать 1D-вектор с моим собственным индексированием или многомерный вектор нормально?

В моем текущем проекте производительность является приоритетом (сначала я знаю код, а затем профиль, но этот проект импортируется на C++ с другого языка для скорости). Я видел, как только один векторный объект может уменьшить накладные расходы, но разве это намного больше, чем часто вычисление индексов? Я видел один ответ отметил, что с помощью вложенных векторов:

vector < vector<int> > 

Вызывает много звонков new. Я видел, как это волнует, это правда?

+0

Существует семантическая разница: вложенные '' '' '' '' '' '' позволяют так называемым зубчатым массивам, где 'arr [i] .size()! = A [j] .size()' для некоторого 'i =! j'. – delnan

+0

Это можно сделать с помощью одномерного вектора и более сложной схемы индексирования, верно? –

+0

Не с одним и тем же 1D-вектором вам нужны дополнительные метаданные (вы можете * придумать взломать, чтобы также сохранить это в одном массиве 1D, но это просто ужасная реализация «дополнительных метаданных»). – delnan

ответ

4

Прежде всего, std::vector<std::vector<int>> может иметь внутренние векторы разного размера. Тем не менее, я предполагаю, что вы говорите конкретно об использовании этого типа для имитации 2D-массивов. Предполагая, что вы создаете размеры векторов при их создании, вам, вероятно, не нужно беспокоиться о количестве динамического распределения, поскольку все это происходит за один раз.

Вектор внутренне выделяет массив своих элементов. Таким образом, внешний вектор выделяет массив векторов, и каждый из этих внутренних векторов выделяет массив из int. Вы можете думать об этом так:

┌─────┐ 
│ vec │ 
└──╂──┘ 
    ┃ 
    ▼ 
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ 
│ vec │ vec │ vec │ vec │ vec │ vec │ vec │ vec │ vec │ 
└──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┴──╂──┘ 
    ┃  ┗━━━━━━━━━━┓ 
    ▼    ▼ 
┌─────┬─────┬┄ ┌─────┬─────┬┄ 
│ int │ int │ │ int │ int │ 
└─────┴─────┴┄ └─────┴─────┴┄ 

Как вы можете видеть, массивы int с полностью отделены друг от друга. Они могут находиться в совершенно разных местах памяти. Это называется фрагментацией. Они почти наверняка не будут в одном непрерывном блоке памяти. Из-за этого доступ к элементам из разных «строк» ​​вашего 2D-вектора, скорее всего, приведет к промахам в кеше.

Однако, если выделить один вектор int с и сделать свой собственный 2-мерную индексацию, то есть макет памяти больше как это:

┌─────┐ 
│ vec │ 
└──╂──┘ 
    ┃ 
    ▼ 
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬┄ 
│ int │ int │ int │ int │ int │ int │ int │ int │ int │ 
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴┄ 

В int s теперь хранятся в один непрерывный блок памяти. Любой доступ, вероятно, будет иметь похожие адреса памяти и приведет к удалению кеша. Это потенциально может дать вам прирост производительности.

+0

Вы также должны изучить [std :: valarray] (http://www.cplusplus.com/reference/valarray/valarray/). Он обеспечивает улучшенную производительность для некоторых операций, а также обеспечивает быстрый доступ к подчастим с помощью [std :: slice] (http://www.cplusplus.com/reference/valarray/slice/) и [std :: gslice] (http://www.cplusplus.com/reference/valarray/gslice/) – TAS