21.12.2020

Тестирую целочисленные операции

Ну уж коли я тут как-то намедни написал функции поиска обратного элемента, грех этим было не воспользоваться, что бы оценить целочисленную производительность современных процессоров. Что я собственно и сделал.
Запустил сначала однопоточный тест на своем
AMD FX-4350, получил результаты и подумал, что, наверное, делать многопоточный тест смысле нет: все же чистая синтетика, 100% регистровых операций, ни одного обращения к памяти...
Но потом вспомнил про HyperThreading, CMT, SMT и вот это вот всё. Поэтому все же прогнал многопоточный тест и сильно удивился!

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

Мой родной AMD FX-4350 показал в многопотоке на чисто регистровых операциях ускорение всего-то в 1.7 раза на классическом Евклиде и в 1.4 (!) на бинарном. Честно говоря, я был в шоке! Попялился на всякий случай на код и ничего там криминального не нашел.
Надо было не тупо пялиться, а ошибку искать. 😕
Что же меня смутило? Вообще-то процессор четырехядерный (на самом деле не совсем), все операции регистровые, поэтому ускорение теоретически должно было бы равняться числу ядер, то есть четырем.
В реальности мой процессор состоит из двух модулей (то есть физически у него два ядра), но в каждом модуле по два полноценных АЛУ, которые представлены как два виртуальных ядра. Это так называемая технология CMT (
Clustered Multithreading) от AMD, некий аналог HyperThreading от Intel.
Но даже если с CMT все так плохо, то все же двукратное ускорение должно же было бы получиться. Но ведь и его не выходит! Причем бинарный вариант, использующий самые простые арифметические операции: сложение и сдвиги, показывает наихудший коэффициент ускорения в многопоточном варианте!
Честно говоря, я не знаю, в чем тут дело. Складывается впечатление, что одно АЛУ вообще общее на все ядра. Поэтому одновременное исполнение максимум четырех команд возможно лишь когда активно одно виртуальное ядро. А другие ядра в это время простаивают или ждут завершение длинной операции, такой как обращение к памяти, умножение или деление.
Похоже, именно поэтому
вариант поиска обратного элемента на классическом алгоритме Евклида показывает более высокое ускорение: пока один поток ждет завершение операции деления, остальные успевают сделать несколько простых вспомогательных арифметических операций.

Впрочем, такое поведение характерно не только для PileDriver. Наименьшее ускорение для бинарного варианта (1.1) показали мобильные AMD A10-4600M и Intel i3-3227U.
Впрочем, более мощные процессоры не намного лучше:
Intel i5-8300H и Intel i7-6700HQ показывают ускорение 2.1 и 2.0 соответственно (по 4 физических ядра), а Ryzen 5 3600 ‒ 2.8 при 6 физических ядрах.
И все они показывают лучшее ускорение при использовании алгоритма с делением.

В связи с чем я с ностальгией вспоминаю свой старенький шестиядерный Phenom II. Похоже, это был последний процессор с относительно честной многоядерностью.
К сожалению, протестировать его нет возможности, так как несколько лет назад сгорела мать, при ее замене я недооценил степень развития собственной дальнозоркости и со слепу нечаянно спалил и
Phenom II при замене материнки.
При замене на
AMD FX-4350 я сразу заметил, что система стала менее отзывчивой. Я связывал это с тем, что поменялся южный мост, но, возможно дело не только в нем. Конечно, пиковая производительность у FX-4350 выше, чем у Phenom II, но вот насчет многозадачности я сейчас уже не уверен.

Ну и наконец-то собственно сама производительность. В качестве базы я, как обычно взял свой AMD FX-4350, поэтому его производительность везде принята за единицу.
Производительность сложения и сдвига я считаю в 1.5 раза более ценной, чем операции деления (так как встречаются в коде они гораздо чаще), как и производительность однопоточного выполнения.

Графики тоже удалил, так как они ошибочны.

Как можем видеть, в целочисленных регистровых операциях даже относительно новые, хоть и мобильные процессоры Intel с трудом тягаются со стареньким десктопным AMD. Ну а относительно новый Ryzen 5, теперь уже предыдущего поколения, вообще для них недостижим.
Так что и в самом деле архитектура Ryzen очень хороша. Хоть она, похоже, чуть-чуть хуже в операциях с плавающей точкой, но опережает в целочисленных, что для большинства приложений важнее. За исключением, может быть, трехмерных игр и приложений ИИ.

Посмотрим более детально. Вариант с использованием операции деления.

Если в функции встречается операция деления, то тут даже старенький процессор от AMD предпочтительней новых изделий от Intel. А Ryzen так вообще рвет все интеловские процессоры, как Тузик грелку.

Бинарный вариант на сложениях и сдвигах.

Тут Intel в последних поколениях в однопотоке немного обогнала PileDriver, но Ryzen 3000 это компенсировал и на обычных целочисленных регистровых операциях AMD и Intel сейчас на равных, но за счет большего количества ядер в общем зачете все же AMD впереди.

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

  1. Замечательно! Ваши тесты подтвердили мою теорию в предыдущем посте: у AMD 64-битное деление и впрямь более чем в 2 раза быстрее чем у Intel.

    С многопоточностью как-то и впрямь неожиданно. А как многопоточный тест организован? Может из-за синхронизации потоков происходит замедление? Можете код выложить?

    ОтветитьУдалить
    Ответы
    1. Попытался вставить в комментарий код, но ни оформления, ни картинки вставить нельзя. Чего-то совсем печально. Сделаю отдельным постом.

      Удалить