C++ Array vs Vector Объяснение теста производительности

Чтобы измерить разницу в производительности массива C-like и Векторов в C++, я написал эту небольшую программу. https://github.com/rajatkhanduja/Benchmarks/blob/master/C%2B%2B/vectorVsArray.cpp

Чтобы сравнить их по общему признаку, я решил проверить как случайный, так и последовательный доступ. Я добавил итераторы, просто чтобы сравнить их (но это не то, на чем сосредоточен вопрос).

Результаты для 64-разрядной машины Linux с 7,7 ГБ ОЗУ с размером массива / вектора 1 миллион выглядят следующим образом:

  • Время, необходимое для записи в массив.: 12,0378 мс
  • Время, необходимое для чтения из массива последовательно.: 2,44813 мс
  • Время, необходимое для чтения из массива в случайном порядке.: 37,3931 мс
  • Время, необходимое для записи в динамический массив.: 11,7458 мс
  • Время, необходимое для чтения из динамического массива последовательно.: 2,85107 мс
  • Время, необходимое для чтения из динамического массива случайным образом.: 36,0579 мс
  • Время, необходимое для записи в вектор с использованием индексов.: 11,3909 мс
  • Время, необходимое для чтения из вектора с использованием индексов, последовательно.: 4.09106 мс
  • Время, затраченное на чтение из вектора с использованием индексов, случайным образом.: 39 мс
  • Время, необходимое для записи в вектор с использованием итераторов.: 24.9949 мс
  • Время, затраченное на чтение из вектора с использованием итераторов.: 18,8049 мс

Размер вектора устанавливается во время инициализации и не изменяется, поэтому изменение размера вектора не выполняется (утверждение в программе помогает это проверить). Времена не включают время инициализации какого-либо статически распределенного массива, динамически распределенного массива или вектора.

Согласно статистике, время записи в Vector меньше, чем у массива, но время чтения из вектора в два раза больше, чем у массива.

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

Код:

#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <sys/time.h>
#include <cassert>

#define ARR_SIZE 1000000

using std::string;

void printtime (struct timeval& start, struct timeval& end, string str);   

int main (void)
{
  int arr[ARR_SIZE];
  int tmp;
  struct timeval start, stop;

  srand (time (NULL));

  /* Writing data to array */
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    arr[i] = rand();
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to write to array."));

  /* Reading data from array */
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = arr[i];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from array sequentially."));

  /* Reading data from array randomly*/
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = arr[rand() % ARR_SIZE];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from array randomly."));


  int *darr = (int *) calloc (sizeof (int), ARR_SIZE);  

  /* Writing data to array */
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    darr[i] = rand();
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to write to dynamic array."));

  /* Reading data from array */
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = darr[i];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from dynamic array sequentially."));

  /* Reading data from dynamic array randomly*/
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = darr[rand() % ARR_SIZE];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from dynamic array randomly."));

  std::vector<int> v(ARR_SIZE);
  assert (v.capacity() == ARR_SIZE);

  /* Writing to vector using indices*/
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    v[i] = rand();
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to write to vector using indices."));
  assert (v.capacity() == ARR_SIZE);

  /* Reading from vector using indices*/
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = v[i];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from vector using indices, sequentially."));

  /* Reading data from dynamic array randomly*/
  gettimeofday (&start, NULL);
  for (int i = 0; i < ARR_SIZE; i++)
  {
    tmp = v[rand() % ARR_SIZE];
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from vector using indices, randomly."));

  std::vector<int> v2(ARR_SIZE);

  /* Writing to vector using iterators*/
  gettimeofday (&start, NULL);
  std::vector<int>::iterator itr, itr_end;
  for (itr = v2.begin(), itr_end = v2.end(); itr != itr_end; itr++)
  {
    *itr = rand();
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to write to vector using iterators."));


  /* Reading from vector using iterators*/
  gettimeofday (&start, NULL);
  for (itr = v2.begin(), itr_end = v2.end(); itr != itr_end; itr++)
  {
    tmp = *itr;
  }
  gettimeofday (&stop, NULL);
  printtime (start, stop, string ("Time taken to read from vector using iterators."));

  return 0;
}

void printtime (struct timeval& start, struct timeval& end, string str)
{
  double start_time, end_time, diff;

  start_time = ((start.tv_sec) * 1000 + start.tv_usec/1000.0);
  end_time   = ((end.tv_sec) * 1000 + end.tv_usec/1000.0);
  diff = end_time - start_time;

  std::cout << str << " : " << diff << " ms" << std::endl;
}

РЕДАКТИРОВАТЬ

Как предлагается в комментариях, здесь больше информации:

  • Компилятор:- g++ - 4.5.2
  • Флаги: - нет (т.е. значения по умолчанию)
  • Оптимизации: - Нет (я хотел протестировать поведение в обычном режиме. Оптимизация может изменить поведение программы, например, поскольку переменная tmp никогда не используется, шаг чтения вектора / массива можно вообще пропустить или уменьшить до только последнее задание. По крайней мере это я так понимаю).

1 ответ

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

Другие вопросы по тегам