Код выделил 20 блоков по одному миллиарду коротких целых.В 64-битном Windows-боксе короткое int составляет 2 байта.Таким образом, выделение составляет ~ 40 гигабайт.
Вы говорите, что 24 ядра, и все они исчерпаны.Код, как он есть, не показывает какой-либо параллелизм.Способ параллелизации кода может оказать глубокое влияние на производительность.Возможно, вам потребуется предоставить дополнительную информацию.
-
Ваша основная проблема, я подозреваю, связана с поведением кэша и ограничениями доступа к памяти.
Во-первых, с двумя физическими процессорамииз шести ядер вы будете полностью насыщать свою шину памяти.Вероятно, у вас в любом случае есть архитектура NUMA, но в коде нет никакого контроля над тем, где размещается ваш calloc () (например, у вас может быть много кода, хранящегося в памяти, для достижения которого требуется несколько прыжков).
Гиперпоточностьвключенный.Это эффективно вдвое уменьшает размер кэша.Поскольку код привязан к шине памяти, а не к вычислениям, гиперпоточность вредна.(Сказав, что, если вычисления в любом случае постоянно находятся за пределами кеша, это не сильно изменится).
Неясно (так как некоторые / много?) Код удаляется, как осуществляется доступ к массиву имодель доступа и оптимизация этого шаблона для обеспечения оптимизации кэша являются ключом к производительности.
Что я вижу в том, как рассчитывается offset (), так это то, что код постоянно требует генерации новых поисков виртуальных и физических адресов- для каждого из которых требуется что-то вроде четырех или пяти обращений к памяти.Это само по себе невероятное быстродействие.
Мой основной совет - разбить массив на блоки размером 2 кеша, дать один блок каждому ЦП и позволить ему обрабатывать этот блок.Вы можете сделать это параллельно.На самом деле, вы можете использовать гиперпоточность для предварительной загрузки кэша, но это более продвинутый метод.