15.07.2020

Доделки тестера

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

В общем, можно сказать, что совместную работу нескольких процессоров можно тестировать по большому счету в двух режимах: параллельном и кооперативном.

В параллельном режиме процессоры решают независимые друг от друга задачи. Теоретически в этом случае можно получить ускорение вычислений, кратное числу процессоров. Практически же параллельную их работу будет ограничивать пропускная способность шины памяти, а в случае многоядерных процессоров еще и внутренняя шина между кэшем L3 и каждым ядром. Зато тест (да и работа) в этом режиме организуется максимально просто.
Близкое к теоретическому ускорение можно получить, решаю очень сложную в вычислительном плане задачу, которая занимает мало памяти, например, целиком помещаясь  в кэше L1 или меньше.
Применительно же к моему методу тестирование параллельный режим состоит в том, что каждый процессор решает свой независимый набор систем линейных алгебраических уравнений (СЛАУ).

Кооперативный же режим предполагает, что процессоры совместно решают одну задачу. Для рассматриваемого теста - это когда одну большую СЛАУ решают сразу несколько процессоров. В принципе, метод Гаусса-Жордана относительно легко укладывается в этот режим, но все же гораздо сложнее, чем параллельный.
Поэтому реализацию кооперативного режима я решил отложить до более поздних времен, хоть общие принципы решения достаточно понятны.
Но могу предположить, что в этом режиме ускорение будет еще меньше, чем в параллельном, так как конфликты при обращении к памяти будут чаще. Кроме того, часть данных может быть кэширована в L1/L2 одного ядра, когда к нему обратится второе, что скорее всего приведет к дополнительным задержкам. И тут может сыграть различная система организаций кэша в процессорах Intel и AMD. Вроде как раньше в AMD кэш был строго эксклюзивным, в то время как в Intel наоборот, инклюзивным. Но это не точно. Тем не менее, разница в стратегии кэширования может приводить к существенной разнице и в производительности.

Давайте посмотрим, что показали параллельные тесты.
Для начала мой родной, сильно постаревший и сильно бюджетный AMD FX-4350, имеющий 4 ядра. Для FPU32 и СЛАУ из 48 переменных параллельный режим дает ускорение примерно в 2.9 раза. По мере роста размерности ускорение падает до 2.3 для 768 переменных.
Сначала я предположил, что это связано с характером вычислений, идущих построчно по матрице. Чем длиннее строка, тем больше скорость развивает конвейер процессора, тем интенсивнее обращение к памяти и больше конфликтов между процессорами за доступ к шине. При переходе на следующую строчку, конвейер сбрасывается, кроме того, выполняется достаточно много других операций, что снижает количество обращений к памяти.
Однако такое предположение опровергается тем, что для FPU64, имеющему почти такую же производительность, но в 2 раза большее количество пересылок по шине памяти, ускорение совпадает почти один в один.
Ситуация меняется кардинально при работе с FPU80. Ускорение для СЛАУ 12 переменных составляет 3.5 и по мере увеличения размерности задачи растет, достигая 3.7 для 384 переменных! Предполагаю, что операции с расширенной точностью требуют на одну команду больше и на процессорах AMD выполняются достаточно медленно, снижая таким образом частоту конфликтов при обращении к памяти.
Таким образом, можно считать что на процессорах AMD поколения Piledriver эффективность параллельной работы составляет примерно 75% или чуть меньше при работе FPU.

Теперь посмотрим на мобильные решения от Intel. Начнем со старенького  i3-3227U, это двухядерный процессор с HT, с базовой частотой 1900 МГц с ограниченным теплопакетом, использовался в нетбуках. Этот процессор вообще выпрыгивает из штанов, показывая ускорение  в 2.6 для FPU32. То есть ускорение существенно больше, чем физических ядер! Вот здесь хорошо видно пользу HT. Фактически можно сказать, что HT на двухядерном процессоре добавляет еще пол ядра.
Больше никаких нюансов на этом процессоре нет, для всех типов данных максимальный коэффициент лежит в районе 2.4-2.7, при увеличении размерности коэффициент ускорения монотонно падает, за исключением очень больших размеров СЛАУ. Впрочем, такие размерности процессор решает настолько медленно, что особо я их не тестировал.

Еще один мобильный процессор Intel i7-6700HQ, поновее, 4 ядра, HT, частота 2600 МГц. Выступает чуть хуже предыдущего, из штанов практически не выпрыгивает: на малых размерностях ускорение может быть чуть больше 4, что также больше количества физических ядер. По мере увеличения размерности ускорение монотонно падает, сильно снижаясь после примерно 384 переменных. Видимо, это связано с выходом размера СЛАУ за пределы кзша L2, который у этого процессора равен 1 МБ.

Таким образом, Intel за счет технологии HT имеют некоторое преимущество над AMD, позволяя им практически на 90-100% использоваться физические ядра.
Впрочем, это не говорит о том, что технология AMD (называется CMT) хуже аналогичной Intel (которая называется похоже - SMT). Просто у AMD в Piledriver один исполнительный блок на два ядра. В каждом блоке два кластера для целочисленных операций, и лишь один - для операций с плавающей точкой. У Intel ситуация более честная. Тут скорее удивительно, что не смотря на то, что каждому ядру досталось лишь полкластера для операций с плавающей точкой, AMD все же показывает 75% эффективность параллельной работы.

3 комментария:

  1. На мобильном i5-7267U CPU @ 3.10GHz (2 физических ядра, HT) у меня ускорение получилось от 1.7 (4096 переменных) до 2 (128 переменных) в параллельном режиме, но цифры сильно плавают, возможно процессор перегревается и частота снижается, но это только теория. Больше 2-х я у себя не увидел, возможно SIMD инструкции и развернутый цикл целиком загрузил физическое ядро, но опять же это теория.

    Интересно было бы запустить на новом монстре от AMD с кучей ядер или хотя бы на полноценном Intel с нормальным охлаждением и кэшем, но увы мой рабочий i7 проработав в закрытом офисе где-то месяц, все же стал не доступен, наверное электричество выключали. А дома только ноут. Карантин ё-моё....

    ОтветитьУдалить
    Ответы
    1. Да, я тоже обратил внимание, что на ноутах процессор ведет себе достаточно не стабильно. У меня почему-то получалось, что первые в тесте FPU32 часто показывают худший результат, чем FPU64. Подозреваю, что из-за оптимизации потребления энергии такое происходит. Но ХЗ.

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

      Удалить
    2. Про FPU32 vs FPU64 интересно, у себя я это не заметил, просто цифры очень сильно плавали и я потерял интерес к такому тестированию.

      Как я понимаю разворот цикла и использование множества регистров как раз позволяют избежать ожидание загрузки из памяти, так как современный процессор почти всегда бежит вперед и выполнят несколько инструкций наперед чтобы загрузить конвейер, а вот если цикл не развернут, тогда действительно конвейер и процессор простаивает и HT позволят догрузить его. Зачем-то ведь компилятор это делает :) Но я в этом не эксперт, так мысли в слух.

      Удалить