Я думаю, что проблема чрезмерных промахов связана с отказом механизма предварительной выборки кеша, но, не зная подробностей доступа к памяти, я не могу точно сказать, почему.
Неважно, что ваши массивы очень большие, 50% промахов — это избыточно. Процессор должен избегать промахов, обнаруживая, что вы перебираете массив, и заранее загружая элементы данных, которые вы, вероятно, будете использовать.
Либо шаблон доступа к массиву не является регулярным, и поэтому модуль предварительной выборки в процессоре не определяет шаблон для предварительной выборки, либо у вас проблема с ассоциативностью кэша, то есть элементы в вашей итерации могут сопоставляться с одними и теми же слотами кэша.
Например, предположим, что размер кэша равен 1 МБ, а набор ассоциативностей равен 4. В этом примере кэш будет отображать память, используя младшие 20 бит, во внутренний слот. Если вы шагаете на 1 Мб, то есть ваши итерации составляют ровно 1 Мб, то младшие 20 бит всегда одинаковы и идут в один и тот же слот кеша, новый элемент использует тот же слот кеша, что и старый. Когда вы доберетесь до пятого элемента, все четыре позиции будут использованы, и с этого момента будут только промахи, в таком случае размер вашего кеша фактически равен одному слоту; если вы шагаете на половину размера кеша, то эффективное количество слотов равно 2, чего может быть достаточно, чтобы вообще не было промахов или чтобы было 100% или что-то среднее, в зависимости от того, требует ли ваш шаблон доступа оба слота одновременно или нет.
Чтобы убедиться в этом, создайте игрушечную программу с различными размерами шага, и вы увидите, что те, которые делят или кратны размерам кеша, увеличивают промахи, вы можете использовать valgrind --tool=cachegrind
person
TheCppZoo
schedule
09.06.2015