почему доступ к памяти такой медленный? - PullRequest
1 голос
/ 19 января 2012

У меня очень странная проблема с производительностью, связанная с доступом к памяти. Фрагмент кода:

#include <vector>
using namespace std;

vector<int> arrx(M,-1); 
vector< vector<int> > arr(N,arrx);

...
for(i=0;i<N;i++){
  for(j=0;j<M;j++){
    //>>>>>>>>>>>> Part 1 <<<<<<<<<<<<<<
    // Simple arithmetic operations
    int n1 = 1 + 2;  // does not matter what (actually more complicated)
    // Integer assignment, without access to array
    int n2 = n1;

    //>>>>>>>>>>>> Part 2 <<<<<<<<<<<<<<
    // This turns out to be most expensive part
    arr[i][j] = n1;
  }
}

N и M - некоторые константы порядка 1000 - 10000 или около того. Когда я компилирую этот код (выпускная версия), для его завершения требуется около 15 часов, если комментируется часть 2. С этой частью время выполнения увеличивается до 100+ часов, поэтому почти в 10 раз медленнее. Я ожидал, что операция присваивания будет намного дешевле, чем даже простые арифметические операции. Это действительно так, если мы не используем массивы. Но с этим массивом назначение кажется намного дороже. Я также попробовал 1-D массив вместо 2-D - тот же результат (для 2D, очевидно, медленнее). Я также использовал int ** или int * вместо vector > или vector - опять результат тот же.

Почему у меня такая низкая производительность при назначении массива и я могу это исправить?

Edit: Еще одно наблюдение: во второй части данного кода, если мы изменим присвоение с

arr[i][j] = n1;  // 172 clocks

до

n1 = arr[i][j];  // 16 clocks

скорость (цифры в комментариях) повышается. Еще интереснее, если мы изменим строку:

arr[i][j] = n1; // 172 clocks

до

arr[i][j] = arr[i][j] * arr[i][j]; // 110 clocks

скорость также выше, чем для простого задания Есть ли разница в чтении и записи из / в память? Почему я получаю такое странное представление?

Заранее спасибо!

Ответы [ 5 ]

6 голосов
/ 19 января 2012

Ваши предположения действительно неверны ...

  1. Запись в основную память намного медленнее, чем при простом добавлении.
  2. Если вы не выполните запись, вполне вероятно, что цикл будет полностью оптимизирован.
5 голосов
/ 19 января 2012

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

2 голосов
/ 19 января 2012

Давайте сделаем простую оценку.Типичная тактовая частота процессора в настоящее время составляет около 1-2 ГГц (гига = 10 до девяти).Упрощение (действительно) большого значения означает, что для одной операции процессора требуется около 1 нс (nano = 10 для питания отрицательных девяти).Простая арифметика типа сложения int занимает несколько циклов ЦП, порядка десяти.

Теперь память: типичное время доступа к памяти составляет около 50 нс (опять же, сейчас не нужно вдаваться в подробности, которых много).

Вы видите, что даже в самом лучшем случае память медленнее, чем центральный процессор, примерно в 5-10 раз.

На самом деле, я подметаю огромный коврикколичество деталей, но я надеюсь, что основная идея ясна.Если вам интересно, вокруг есть книги (ключевые слова: кеш, ошибки кеша, локальность данных и т. Д.). Этот датирован, но все еще очень хорош в объяснении общих понятий.

2 голосов
/ 19 января 2012

Ваши вложенные массивы будут где-то в области 50–500 МБ памяти. Требуется время для записи такого большого объема памяти, и никакое количество умного аппаратного кэширования памяти не поможет так много. Более того, даже одна запись в память займет время, так как она должна пройти через несколько медных проводов на плате к кусочку кремния на некотором расстоянии; физика побеждает.

Но если вы хотите узнать больше, попробуйте инструмент cachegrind (если он присутствует на вашей платформе). Просто имейте в виду, что код, который вы используете выше, на самом деле не позволяет много оптимизации; его схема доступа к данным не обладает огромным потенциалом повторного использования.

2 голосов
/ 19 января 2012

Вы обнаружили печальную правду о современных компьютерах: доступ к памяти очень медленный по сравнению с арифметикой. Вы ничего не можете с этим поделать. Это связано с тем, что электрические поля в медном проводе движутся со скоростью около двух третей скорости света.

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