26.07.2020

Тестер. Первые результаты

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

FPU32. СЛАУ из 3-х уравнений AMD FX-4350 решает 8.5 млн./сек. Это несколько отличается от значения, которое я приводил в самой первой статье. Объясняется просто: там я оценивал производительность, решая много раз одну и ту же СЛАУ, поэтому данные попали в кэш первого уровня и производительность была больше. В конечно же варианте теста производительность оценивается при решении разных систем.
i3-3227U обеспечивает 6.7 млн./сек, а i7-6700HQ - 13.6 млн./сек.

FPU64. СЛАУ из 3-х уравнений FX-4350 решает также 8.5 млн./сек., i3-3227U - 6.7 млн./сек., а вот i7-6700HQ настолько быстр, что в 32-разрядном режиме памяти под все системы не хватило, что бы время решения было примерно 1 секунду. И для система из 6 уравнений тоже.
Системы же из 12 уравнений этот процессор решает 792 тыс./сек., FX-4350 - 454 тыс./сек, i3-3227U - 407 тыс./сек.

FPU80. СЛАУ из 3-х уравнений FX-4350 решает также 3.5 млн./сек., а (сюрприз!) i3-3227U - 4.5 млн./сек. То есть маленький, крохотный процессор для нетбуков от Intel с тактовой частотой 1900 МГц кроет как бык овцу AMDшный процессор с частотой 4200МГц!  i7-6700HQ опять же оказался настолько быстр, что памяти под такие СЛАУ не хватило.
А вот системы из 6-ти уравнений процессоры решили так: FX-4350 - 603 тыс./сек, i3-3227U - 1 млн./сек., i7-6700HQ - 2 млн/сек.

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

Общая оценка. Методика оценки очень проста. Решается набор СЛАУ разных размерностей от 3 до максимальной, на решение которой требуется не более 1 секунды. Увеличение размерности идет по геометрической прогрессии со знаменателем 2.
Процессоры сравниваются только на тех размерностях, которые у них совпадают. Разные типы данных имеют разный приоритет. Для текущей оценки я взял приоритет 0.5 для FPU32, 0.4 для FPU64 и 0.1 для FPU80.
Однопоточная производительность имеет приоритет 0.6, параллельная - 0.4. Если за единицу брать производительность процессора FX-4350, то получается вот такая картинка.
FX-4350 имеет базовую частоту 4200 МГц, частоту шины памяти 1600, i3-3227U - 1900 и 1333 МГц, i7-6700HQ - 2600 и 2133 МГц соответственно

В принципе, можно построить более подробные графики по каждому типы вычислений, но не уверен, нужно ли.

Что дальше? Дальше нужно решить пару проблем.
Первая состоит в том, что я генерирую уникальные СЛАУ для теста случайным образом. В некоторых, очень редких случаях система может получаться не совместной, т. е. либо не имеющей решение, либо требующей более высокой точности при решении, иначе возникает переполнение.
В принципе, при решении реальных СЛАУ такие ситуации нужно просто отслеживать и выдавать предупреждение в ходе решения. Но не в случае замера производительности!
Т. е. надо бы придумать, как сгенерировать случайную гарантированно совместную систему. Пока никаких идей у меня в этом направлении нет. Ну, за исключением того, что бы не генерировать уникальные системы, а сделать лишь одну гарантированно совместную, а потом ее просто скопировать нужно количество раз.

Вторая проблема состоит в том, что современные процессоры очень-очень быстры. А для точного замера производительности нужно решить достаточное количество систем. Я в текущем варианте беру такое количество, которое решается примерно за 1 секунду. В таком режиме погрешность измерения составляет примерно 5% (хотя точно научными методами я ее не оценивал), поэтому уменьшать время не хотелось бы.
Тем более, что производительность настолько высока, что для самых быстрых процессоров пришлось бы ее снижать не в 2 раза, а на порядок и более, что существенно увеличило бы погрешность.

Но в 32-разрядном режиме для маленьких систем у меня не хватает памяти для их размещения! То есть 2 гигабайт памяти, выделяемой программам Windows в 32-разрядном режиме не достаточно, так как время решения всех систем, помещающихся в эту память, меньше 1 секунды! Ситуация еще более усложняется при работе в параллельном режиме, так как там каждому ядру необходимо решить свой отдельный набор СЛАУ.
Кроме того, желая максимально использовать доступную мне память, я допустил где-то досадную ошибку, вызывающее ошибку нехватки памяти, которая возникает только на очень быстрых системах. Из-за этого не удалось оттестировать еще один доступный мне ноутбук.

Таким образом, крайне актуальной задачей является переход на 64-разрядную версию программы. Там есть свои нюансы, но об этом в следующий раз.

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% эффективность параллельной работы.