Сколько объектов может быть повторено в векторе до того, как произойдет промах кэша L3?

Допустим, у меня есть класс, который содержит члены данных с выделенной кучей памяти:

class X{
std::map<int, double> a;
std::set<int> b;
std::vector<int>;
std::string c;
}

и у меня есть std::vector<shared_ptr<X>> содержащий многие из них X объекты, через которые я буду проходить и получить доступ к map.begin ():

for(int i =0; i<vec.size(); i++){
running_total += *(vec[i]->a.begin());
}

Теоретически, сколько объектов я должен быть в состоянии удерживать / перебирать в векторе, прежде чем я столкнусь с отсутствием кэша L3?

Я думал, что ответом будет то, сколько строк кэша на объект может вместить кэш L3, но L3 size / sizeof (x_element.get ()), похоже, не дает мне ответ, который я вижу из профилирования ….

Мой кэш L3 составляет 8 МБ, каждая строка кэша — 64 байта, и поэтому я мог бы хранить около 125 000 объектов до того, как кэш L3 пропадет. Однако я вижу, что кэш L3 пропускает при гораздо меньшем количестве векторных элементов.

2

Решение

На процессорах Intel вы можете использовать Анализатор кода архитектуры Intel (IACA) для анализа вашей петли. Если я правильно помню, он также может анализировать ошибки кэша, если вы правильно настроили его и т. Д.

Другим инструментом является Valgrind, который является симулятором, который также можно использовать для имитации поведения кэша, если вы настроите его правильно.

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

1

Другие решения


По вопросам рекламы [email protected]