Почему доступ к указателю медленнее, чем доступ к вектору::итератору? (генерация кода компилятора)C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Почему доступ к указателю медленнее, чем доступ к вектору::итератору? (генерация кода компилятора)

Сообщение Anonymous »

Хорошо, заголовок вопроса немного дрянной, но я не знаю, как это лучше сформулировать.

У меня проблема в том, что, учитывая стандартное ::vector против T* + size_t count мой компилятор (Visual Studio 2005/VC++ 8) на самом деле будет генерировать худший код при циклическом проходе по указателю, чем при циклическом проходе тот вектор.

То есть у меня есть тестовая структура, содержащая вектор, и другая, содержащая указатель + счетчик. Теперь при написании семантически точно такой же конструкции цикла версия с std::vector значительно (то есть > 10%) быстрее, чем версия с указателем.
Ниже вы найдете код и сгенерированную сборку. Было бы здорово, если бы кто-нибудь мог объяснить, что здесь происходит.

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

И пожалуйста воздержитесь от ответов, рассказывающих меня это не должно волновать, преждевременная оптимизация, корень зла и т. д. В данном конкретном случае меня действительно волнует, и в любом случае я думаю, что это довольно интересная головоломка! :-)



Настройки компилятора:
  • Полная оптимизация (/Ox)
  • Опция всей программы. = НЕТ
Вот код:

stdafx. ч

// Disable secure STL stuff!
#define _SECURE_SCL 0
#define _SECURE_SCL_THROWS 0
#include
#include
#include
#include


файл заголовка

// loop1.h
typedef int PodType;

const size_t container_size = 3;
extern volatile size_t g_read_size;

void side_effect();

struct RawX {
PodType* pData;
PodType wCount;

RawX()
: pData(NULL)
, wCount(0)
{ }

~RawX() {
delete[] pData;
pData = NULL;
wCount = 0;
}

void Resize(PodType n) {
delete[] pData;
wCount = n;
pData = new PodType[wCount];
}
private:
RawX(RawX const&);
RawX& operator=(RawX const&);
};

struct VecX {
std::vector
vData;
};

void raw_loop(const int n, RawX* obj);
void raw_iterator_loop(const int n, RawX* obj);
void vector_loop(const int n, VecX* obj);
void vector_iterator_loop(const int n, VecX* obj);


файл реализации

// loop1.cpp
void raw_loop(const int n, RawX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(int j=0, e=obj->wCount; j!=e; ++j) {
g_read_size = obj->pData[j];
side_effect();
}
side_effect();
}
}

void raw_iterator_loop(const int n, RawX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(PodType *j=obj->pData, *e=obj->pData+size_t(obj->wCount); j!=e; ++j) {
g_read_size = *j;
side_effect();
}
side_effect();
}
}

void vector_loop(const int n, VecX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(size_t j=0, e=obj->vData.size(); j!=e; ++j) {
g_read_size = obj->vData[j];
side_effect();
}
side_effect();
}
}

void vector_iterator_loop(const int n, VecX* obj)
{
for(int i=0; i!=n; ++i) {
side_effect();
for(std::vector
::const_iterator j=obj->vData.begin(), e=obj->vData.end(); j!=e; ++j) {
g_read_size = *j;
side_effect();
}
side_effect();
}
}


основной файл теста

using namespace std;

volatile size_t g_read_size;
void side_effect()
{
g_read_size = 0;
}

typedef size_t Value;

template
Value average(Container const& c)
{
const Value sz = c.size();
Value sum = 0;
for(Container::const_iterator i=c.begin(), e=c.end(); i!=e; ++i)
sum += *i;
return sum/sz;

}

void take_timings()
{
const int x = 10;
const int n = 10*1000*1000;

VecX vobj;
vobj.vData.resize(container_size);
RawX robj;
robj.Resize(container_size);

std::vector raw_times;
std::vector vec_times;
std::vector rit_times;
std::vector vit_times;

for(int i=0; i!=x; ++i) {
const DWORD t1 = timeGetTime();
raw_loop(n, &robj);
const DWORD t2 = timeGetTime();
vector_loop(n, &vobj);
const DWORD t3 = timeGetTime();
raw_iterator_loop(n, &robj);
const DWORD t4 = timeGetTime();
vector_iterator_loop(n, &vobj);
const DWORD t5 = timeGetTime();
raw_times.push_back(t2-t1);
vec_times.push_back(t3-t2);
rit_times.push_back(t4-t3);
vit_times.push_back(t5-t4);
}

cout

Подробнее здесь: https://stackoverflow.com/questions/393 ... ode-genera
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»